1*cb5caa98Sdjl /*
2*cb5caa98Sdjl * CDDL HEADER START
3*cb5caa98Sdjl *
4*cb5caa98Sdjl * The contents of this file are subject to the terms of the
5*cb5caa98Sdjl * Common Development and Distribution License (the "License").
6*cb5caa98Sdjl * You may not use this file except in compliance with the License.
7*cb5caa98Sdjl *
8*cb5caa98Sdjl * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*cb5caa98Sdjl * or http://www.opensolaris.org/os/licensing.
10*cb5caa98Sdjl * See the License for the specific language governing permissions
11*cb5caa98Sdjl * and limitations under the License.
12*cb5caa98Sdjl *
13*cb5caa98Sdjl * When distributing Covered Code, include this CDDL HEADER in each
14*cb5caa98Sdjl * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*cb5caa98Sdjl * If applicable, add the following below this CDDL HEADER, with the
16*cb5caa98Sdjl * fields enclosed by brackets "[]" replaced with your own identifying
17*cb5caa98Sdjl * information: Portions Copyright [yyyy] [name of copyright owner]
18*cb5caa98Sdjl *
19*cb5caa98Sdjl * CDDL HEADER END
20*cb5caa98Sdjl */
21*cb5caa98Sdjl /*
22*cb5caa98Sdjl * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
23*cb5caa98Sdjl * Use is subject to license terms.
24*cb5caa98Sdjl */
25*cb5caa98Sdjl
26*cb5caa98Sdjl #pragma ident "%Z%%M% %I% %E% SMI"
27*cb5caa98Sdjl
28*cb5caa98Sdjl #include <assert.h>
29*cb5caa98Sdjl #include <stdlib.h>
30*cb5caa98Sdjl #include <string.h>
31*cb5caa98Sdjl #include "nscd_db.h"
32*cb5caa98Sdjl #include "nscd_log.h"
33*cb5caa98Sdjl
34*cb5caa98Sdjl /*
35*cb5caa98Sdjl * Access control structure for a piece of nscd data. This structure
36*cb5caa98Sdjl * is always tagged before the nscd data. nscd_alloc, which should
37*cb5caa98Sdjl * be used to allocate memory that requires access control or usage
38*cb5caa98Sdjl * count control, will initialize this access control structure at the
39*cb5caa98Sdjl * start of the memory returned to the caller.
40*cb5caa98Sdjl */
41*cb5caa98Sdjl struct nscd_access_s {
42*cb5caa98Sdjl void *data; /* addr of real data */
43*cb5caa98Sdjl void (*free_func)(nscd_acc_data_t *data); /* destructor */
44*cb5caa98Sdjl mutex_t mutex; /* protect this structure */
45*cb5caa98Sdjl mutex_t *data_mutex;
46*cb5caa98Sdjl rwlock_t *data_rwlock;
47*cb5caa98Sdjl cond_t *data_cond;
48*cb5caa98Sdjl int nUse; /* usage count */
49*cb5caa98Sdjl int type;
50*cb5caa98Sdjl int delete; /* no longer available */
51*cb5caa98Sdjl nscd_seq_num_t seq_num; /* sequence number */
52*cb5caa98Sdjl };
53*cb5caa98Sdjl
54*cb5caa98Sdjl /* size should be in multiple of 8 */
55*cb5caa98Sdjl static int sizeof_access = roundup(sizeof (nscd_access_t));
56*cb5caa98Sdjl
57*cb5caa98Sdjl #define ABORT_DUE_TO_NO_VALID_NSCD_ACCESS_DATA 0
58*cb5caa98Sdjl #define ASSERT_ACCESS_DATA \
59*cb5caa98Sdjl if (access->data != data) \
60*cb5caa98Sdjl assert(ABORT_DUE_TO_NO_VALID_NSCD_ACCESS_DATA)
61*cb5caa98Sdjl
62*cb5caa98Sdjl #define SET_ACCESS_PTR \
63*cb5caa98Sdjl access = (nscd_access_t *) \
64*cb5caa98Sdjl ((void *)((char *)data - sizeof_access))
65*cb5caa98Sdjl
66*cb5caa98Sdjl static void _nscd_free(nscd_acc_data_t *data);
67*cb5caa98Sdjl
68*cb5caa98Sdjl /*
69*cb5caa98Sdjl * FUNCTION: _nscd_release
70*cb5caa98Sdjl *
71*cb5caa98Sdjl * Decrements the usage count maintained in the access data
72*cb5caa98Sdjl * tagged before 'data'. Delete the nscd data item if the delete
73*cb5caa98Sdjl * flag is set and the usage count reaches 0.
74*cb5caa98Sdjl */
75*cb5caa98Sdjl void
_nscd_release(nscd_acc_data_t * data)76*cb5caa98Sdjl _nscd_release(
77*cb5caa98Sdjl nscd_acc_data_t *data)
78*cb5caa98Sdjl {
79*cb5caa98Sdjl nscd_access_t *access;
80*cb5caa98Sdjl char *me = "_nscd_release";
81*cb5caa98Sdjl
82*cb5caa98Sdjl if (data == NULL)
83*cb5caa98Sdjl return;
84*cb5caa98Sdjl
85*cb5caa98Sdjl SET_ACCESS_PTR;
86*cb5caa98Sdjl
87*cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_ACCESS_INFO, NSCD_LOG_LEVEL_DEBUG)
88*cb5caa98Sdjl (me, "data = %p, access->data = %p, "
89*cb5caa98Sdjl "seq = %lld, nUse = %d\n",
90*cb5caa98Sdjl data, access->data, access->seq_num, access->nUse);
91*cb5caa98Sdjl ASSERT_ACCESS_DATA;
92*cb5caa98Sdjl
93*cb5caa98Sdjl (void) mutex_lock(&access->mutex);
94*cb5caa98Sdjl access->nUse--;
95*cb5caa98Sdjl if (access->nUse < 0) {
96*cb5caa98Sdjl #define ACCESS_NUSE_LESS_THAN_ZERO 0
97*cb5caa98Sdjl assert(ACCESS_NUSE_LESS_THAN_ZERO);
98*cb5caa98Sdjl }
99*cb5caa98Sdjl if (access->nUse <= 0 &&
100*cb5caa98Sdjl access->delete == 1) {
101*cb5caa98Sdjl
102*cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_ACCESS_INFO, NSCD_LOG_LEVEL_DEBUG)
103*cb5caa98Sdjl (me, "deleting data %p\n", access->data);
104*cb5caa98Sdjl (access->free_func)(access->data);
105*cb5caa98Sdjl
106*cb5caa98Sdjl /*
107*cb5caa98Sdjl * if we get here, no other thread could be
108*cb5caa98Sdjl * holding the access->mutex lock, It is safe
109*cb5caa98Sdjl * to free the memory containing the mutex
110*cb5caa98Sdjl * structure. No mutex_unlock is necessary.
111*cb5caa98Sdjl */
112*cb5caa98Sdjl _nscd_free(data);
113*cb5caa98Sdjl } else
114*cb5caa98Sdjl (void) mutex_unlock(&access->mutex);
115*cb5caa98Sdjl }
116*cb5caa98Sdjl
117*cb5caa98Sdjl
118*cb5caa98Sdjl /*
119*cb5caa98Sdjl * FUNCTION: _nscd_destroy
120*cb5caa98Sdjl *
121*cb5caa98Sdjl * Marks the nscd data item as to-be-deleted and then releases
122*cb5caa98Sdjl * (If the usage count happens to be zero, then _nscd_release()
123*cb5caa98Sdjl * will destroy the data.)
124*cb5caa98Sdjl *
125*cb5caa98Sdjl * Note that _nscd_destroy should only be called if the
126*cb5caa98Sdjl * caller has created the nscd data with _nscd_alloc
127*cb5caa98Sdjl * (with the exception of _nscd_set). That nscd data
128*cb5caa98Sdjl * item should be private to the caller.
129*cb5caa98Sdjl */
130*cb5caa98Sdjl static void
_nscd_destroy(nscd_acc_data_t * data)131*cb5caa98Sdjl _nscd_destroy(
132*cb5caa98Sdjl nscd_acc_data_t *data)
133*cb5caa98Sdjl {
134*cb5caa98Sdjl nscd_access_t *access;
135*cb5caa98Sdjl char *me = "_nscd_destroy";
136*cb5caa98Sdjl
137*cb5caa98Sdjl if (data == NULL)
138*cb5caa98Sdjl return;
139*cb5caa98Sdjl
140*cb5caa98Sdjl SET_ACCESS_PTR;
141*cb5caa98Sdjl
142*cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_ACCESS_INFO, NSCD_LOG_LEVEL_DEBUG)
143*cb5caa98Sdjl (me, "data = %p, access->data = %p\n", data, access->data);
144*cb5caa98Sdjl ASSERT_ACCESS_DATA;
145*cb5caa98Sdjl
146*cb5caa98Sdjl (void) mutex_lock(&access->mutex);
147*cb5caa98Sdjl access->delete = 1;
148*cb5caa98Sdjl (void) mutex_unlock(&access->mutex);
149*cb5caa98Sdjl
150*cb5caa98Sdjl _nscd_release(data);
151*cb5caa98Sdjl }
152*cb5caa98Sdjl
153*cb5caa98Sdjl /*
154*cb5caa98Sdjl * FUNCTION: _nscd_get
155*cb5caa98Sdjl *
156*cb5caa98Sdjl * Increment the usage count by one if 'data' can
157*cb5caa98Sdjl * be found in the internal address database.
158*cb5caa98Sdjl */
159*cb5caa98Sdjl nscd_acc_data_t *
_nscd_get(nscd_acc_data_t * data)160*cb5caa98Sdjl _nscd_get(
161*cb5caa98Sdjl nscd_acc_data_t *data)
162*cb5caa98Sdjl {
163*cb5caa98Sdjl nscd_access_t *access;
164*cb5caa98Sdjl void *ret = data;
165*cb5caa98Sdjl rwlock_t *addr_rwlock;
166*cb5caa98Sdjl char *me = "_nscd_get";
167*cb5caa98Sdjl
168*cb5caa98Sdjl if (data == NULL)
169*cb5caa98Sdjl return (NULL);
170*cb5caa98Sdjl
171*cb5caa98Sdjl SET_ACCESS_PTR;
172*cb5caa98Sdjl
173*cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_ACCESS_INFO, NSCD_LOG_LEVEL_DEBUG)
174*cb5caa98Sdjl (me, "data = %p, access->data = %p, seq#= %lld, nUse = %d\n",
175*cb5caa98Sdjl data, access->data, access->seq_num, access->nUse);
176*cb5caa98Sdjl ASSERT_ACCESS_DATA;
177*cb5caa98Sdjl
178*cb5caa98Sdjl /*
179*cb5caa98Sdjl * see if this addr is still valid,
180*cb5caa98Sdjl * if so, _nscd_is_int_addr will
181*cb5caa98Sdjl * do a read lock on the returned
182*cb5caa98Sdjl * multiple readers/single writer lock
183*cb5caa98Sdjl * to prevent the access data from being
184*cb5caa98Sdjl * deleted while it is being accessed.
185*cb5caa98Sdjl */
186*cb5caa98Sdjl if ((addr_rwlock = _nscd_is_int_addr(data,
187*cb5caa98Sdjl access->seq_num)) == NULL) {
188*cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_ACCESS_INFO, NSCD_LOG_LEVEL_DEBUG)
189*cb5caa98Sdjl (me, "internal address %p not found\n", data);
190*cb5caa98Sdjl assert(addr_rwlock != NULL);
191*cb5caa98Sdjl return (NULL);
192*cb5caa98Sdjl }
193*cb5caa98Sdjl
194*cb5caa98Sdjl (void) mutex_lock(&access->mutex);
195*cb5caa98Sdjl if (access->delete == 1)
196*cb5caa98Sdjl ret = NULL;
197*cb5caa98Sdjl else
198*cb5caa98Sdjl access->nUse++;
199*cb5caa98Sdjl (void) mutex_unlock(&access->mutex);
200*cb5caa98Sdjl
201*cb5caa98Sdjl /*
202*cb5caa98Sdjl * done with the multiple readers/single writer lock
203*cb5caa98Sdjl */
204*cb5caa98Sdjl (void) rw_unlock(addr_rwlock);
205*cb5caa98Sdjl
206*cb5caa98Sdjl return (ret);
207*cb5caa98Sdjl }
208*cb5caa98Sdjl
209*cb5caa98Sdjl /*
210*cb5caa98Sdjl * FUNCTION: _nscd_set
211*cb5caa98Sdjl *
212*cb5caa98Sdjl * _nscd_set sets the address of a nscd data item
213*cb5caa98Sdjl * to 'new' and delete the old nscd data (old).
214*cb5caa98Sdjl * The pointer 'new' is returned.
215*cb5caa98Sdjl */
216*cb5caa98Sdjl nscd_acc_data_t *
_nscd_set(nscd_acc_data_t * old,nscd_acc_data_t * new)217*cb5caa98Sdjl _nscd_set(
218*cb5caa98Sdjl nscd_acc_data_t *old,
219*cb5caa98Sdjl nscd_acc_data_t *new)
220*cb5caa98Sdjl {
221*cb5caa98Sdjl nscd_acc_data_t *old_data, *new_data;
222*cb5caa98Sdjl char *me = "_nscd_set";
223*cb5caa98Sdjl
224*cb5caa98Sdjl if (new == old)
225*cb5caa98Sdjl return (old);
226*cb5caa98Sdjl
227*cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_ACCESS_INFO, NSCD_LOG_LEVEL_DEBUG)
228*cb5caa98Sdjl (me, "new = %p, old = %p\n", new, old);
229*cb5caa98Sdjl
230*cb5caa98Sdjl old_data = _nscd_get(old);
231*cb5caa98Sdjl new_data = _nscd_get(new);
232*cb5caa98Sdjl
233*cb5caa98Sdjl if (old_data != new_data) {
234*cb5caa98Sdjl
235*cb5caa98Sdjl _nscd_destroy(old_data);
236*cb5caa98Sdjl _nscd_release(new_data);
237*cb5caa98Sdjl return (new_data);
238*cb5caa98Sdjl }
239*cb5caa98Sdjl
240*cb5caa98Sdjl /* if old_data == new_data, both must be NULL */
241*cb5caa98Sdjl return (NULL);
242*cb5caa98Sdjl }
243*cb5caa98Sdjl
244*cb5caa98Sdjl /*
245*cb5caa98Sdjl * FUNCTION: _nscd_rdlock
246*cb5caa98Sdjl *
247*cb5caa98Sdjl * Lock (rw_rdlock) a nscd data item for reading. The caller
248*cb5caa98Sdjl * needs to call _nscd_rw_unlock() to unlock the data item
249*cb5caa98Sdjl * when done using the data.
250*cb5caa98Sdjl */
251*cb5caa98Sdjl nscd_acc_data_t *
_nscd_rdlock(nscd_acc_data_t * data)252*cb5caa98Sdjl _nscd_rdlock(
253*cb5caa98Sdjl nscd_acc_data_t *data)
254*cb5caa98Sdjl {
255*cb5caa98Sdjl nscd_access_t *access;
256*cb5caa98Sdjl void *ret;
257*cb5caa98Sdjl char *me = "_nscd_rdlock";
258*cb5caa98Sdjl
259*cb5caa98Sdjl ret = _nscd_get(data);
260*cb5caa98Sdjl
261*cb5caa98Sdjl if (ret == NULL)
262*cb5caa98Sdjl return (NULL);
263*cb5caa98Sdjl
264*cb5caa98Sdjl SET_ACCESS_PTR;
265*cb5caa98Sdjl
266*cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_ACCESS_INFO, NSCD_LOG_LEVEL_DEBUG)
267*cb5caa98Sdjl (me, "data = %p, access->data = %p\n", data, access->data);
268*cb5caa98Sdjl ASSERT_ACCESS_DATA;
269*cb5caa98Sdjl
270*cb5caa98Sdjl assert(access->data_rwlock != NULL);
271*cb5caa98Sdjl
272*cb5caa98Sdjl (void) rw_rdlock(access->data_rwlock);
273*cb5caa98Sdjl
274*cb5caa98Sdjl return (ret);
275*cb5caa98Sdjl }
276*cb5caa98Sdjl
277*cb5caa98Sdjl /*
278*cb5caa98Sdjl * FUNCTION: _nscd_wrlock
279*cb5caa98Sdjl *
280*cb5caa98Sdjl * Lock (rw_wrlock) a nscd data item for writing. The caller
281*cb5caa98Sdjl * needs to call _nscd_rw_unlock() to unlock the data item
282*cb5caa98Sdjl * when done using the data.
283*cb5caa98Sdjl */
284*cb5caa98Sdjl nscd_acc_data_t *
_nscd_wrlock(nscd_acc_data_t * data)285*cb5caa98Sdjl _nscd_wrlock(
286*cb5caa98Sdjl nscd_acc_data_t *data)
287*cb5caa98Sdjl {
288*cb5caa98Sdjl nscd_access_t *access;
289*cb5caa98Sdjl void *ret;
290*cb5caa98Sdjl char *me = "_nscd_wrlock";
291*cb5caa98Sdjl
292*cb5caa98Sdjl ret = _nscd_get(data);
293*cb5caa98Sdjl
294*cb5caa98Sdjl if (ret == NULL)
295*cb5caa98Sdjl return (NULL);
296*cb5caa98Sdjl
297*cb5caa98Sdjl SET_ACCESS_PTR;
298*cb5caa98Sdjl
299*cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_ACCESS_INFO, NSCD_LOG_LEVEL_DEBUG)
300*cb5caa98Sdjl (me, "data = %p, access->data = %p\n", data, access->data);
301*cb5caa98Sdjl ASSERT_ACCESS_DATA;
302*cb5caa98Sdjl
303*cb5caa98Sdjl assert(access->data_rwlock != NULL);
304*cb5caa98Sdjl
305*cb5caa98Sdjl (void) rw_wrlock(access->data_rwlock);
306*cb5caa98Sdjl
307*cb5caa98Sdjl return (ret);
308*cb5caa98Sdjl }
309*cb5caa98Sdjl
310*cb5caa98Sdjl /*
311*cb5caa98Sdjl * FUNCTION: _nscd_rw_unlock
312*cb5caa98Sdjl *
313*cb5caa98Sdjl * Unlock (rw_unlock) a locked nscd data item.
314*cb5caa98Sdjl */
315*cb5caa98Sdjl void
_nscd_rw_unlock(nscd_acc_data_t * data)316*cb5caa98Sdjl _nscd_rw_unlock(
317*cb5caa98Sdjl nscd_acc_data_t *data)
318*cb5caa98Sdjl {
319*cb5caa98Sdjl nscd_access_t *access;
320*cb5caa98Sdjl char *me = "_nscd_rw_unlock";
321*cb5caa98Sdjl
322*cb5caa98Sdjl if (data == NULL)
323*cb5caa98Sdjl return;
324*cb5caa98Sdjl
325*cb5caa98Sdjl SET_ACCESS_PTR;
326*cb5caa98Sdjl
327*cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_ACCESS_INFO, NSCD_LOG_LEVEL_DEBUG)
328*cb5caa98Sdjl (me, "data = %p, access->data = %p\n",
329*cb5caa98Sdjl data, access->data);
330*cb5caa98Sdjl ASSERT_ACCESS_DATA;
331*cb5caa98Sdjl
332*cb5caa98Sdjl assert(access->data_rwlock != NULL);
333*cb5caa98Sdjl
334*cb5caa98Sdjl (void) rw_unlock(access->data_rwlock);
335*cb5caa98Sdjl _nscd_release(data);
336*cb5caa98Sdjl }
337*cb5caa98Sdjl
338*cb5caa98Sdjl /*
339*cb5caa98Sdjl * FUNCTION: _nscd_rw_unlock_no_release
340*cb5caa98Sdjl *
341*cb5caa98Sdjl * Unlock (rw_unlock) a locked nscd data item but without release
342*cb5caa98Sdjl * it, i.e., without decrement the usage count to indicate that
343*cb5caa98Sdjl * the data item is still being referenced.
344*cb5caa98Sdjl */
345*cb5caa98Sdjl void
_nscd_rw_unlock_no_release(nscd_acc_data_t * data)346*cb5caa98Sdjl _nscd_rw_unlock_no_release(
347*cb5caa98Sdjl nscd_acc_data_t *data)
348*cb5caa98Sdjl {
349*cb5caa98Sdjl nscd_access_t *access;
350*cb5caa98Sdjl
351*cb5caa98Sdjl if (data == NULL)
352*cb5caa98Sdjl return;
353*cb5caa98Sdjl
354*cb5caa98Sdjl SET_ACCESS_PTR;
355*cb5caa98Sdjl ASSERT_ACCESS_DATA;
356*cb5caa98Sdjl
357*cb5caa98Sdjl assert(access->data_rwlock != NULL);
358*cb5caa98Sdjl
359*cb5caa98Sdjl (void) rw_unlock(access->data_rwlock);
360*cb5caa98Sdjl }
361*cb5caa98Sdjl
362*cb5caa98Sdjl /*
363*cb5caa98Sdjl * FUNCTION: _nscd_mutex_lock
364*cb5caa98Sdjl *
365*cb5caa98Sdjl * Lock (mutex_lock) a nscd data item. The caller needs
366*cb5caa98Sdjl * to call _nscd_mutex_unlock() to unlock the data item
367*cb5caa98Sdjl * when done using the data.
368*cb5caa98Sdjl */
369*cb5caa98Sdjl nscd_acc_data_t *
_nscd_mutex_lock(nscd_acc_data_t * data)370*cb5caa98Sdjl _nscd_mutex_lock(
371*cb5caa98Sdjl nscd_acc_data_t *data)
372*cb5caa98Sdjl {
373*cb5caa98Sdjl nscd_access_t *access;
374*cb5caa98Sdjl void *ret;
375*cb5caa98Sdjl char *me = "_nscd_mutex_lock";
376*cb5caa98Sdjl
377*cb5caa98Sdjl ret = _nscd_get(data);
378*cb5caa98Sdjl
379*cb5caa98Sdjl if (ret == NULL)
380*cb5caa98Sdjl return (NULL);
381*cb5caa98Sdjl
382*cb5caa98Sdjl SET_ACCESS_PTR;
383*cb5caa98Sdjl
384*cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_ACCESS_INFO, NSCD_LOG_LEVEL_DEBUG)
385*cb5caa98Sdjl (me, "data = %p, access->data = %p\n", data, access->data);
386*cb5caa98Sdjl ASSERT_ACCESS_DATA;
387*cb5caa98Sdjl
388*cb5caa98Sdjl assert(access->data_mutex != NULL);
389*cb5caa98Sdjl
390*cb5caa98Sdjl (void) mutex_lock(access->data_mutex);
391*cb5caa98Sdjl
392*cb5caa98Sdjl return (ret);
393*cb5caa98Sdjl }
394*cb5caa98Sdjl
395*cb5caa98Sdjl
396*cb5caa98Sdjl /*
397*cb5caa98Sdjl * FUNCTION: _nscd_mutex_unlock
398*cb5caa98Sdjl *
399*cb5caa98Sdjl * Unlock a locked nscd data item (that were locked by _nscd_mutex_lock)..
400*cb5caa98Sdjl */
401*cb5caa98Sdjl void
_nscd_mutex_unlock(nscd_acc_data_t * data)402*cb5caa98Sdjl _nscd_mutex_unlock(
403*cb5caa98Sdjl nscd_acc_data_t *data)
404*cb5caa98Sdjl {
405*cb5caa98Sdjl nscd_access_t *access;
406*cb5caa98Sdjl char *me = "_nscd_mutex_unlock";
407*cb5caa98Sdjl
408*cb5caa98Sdjl if (data == NULL)
409*cb5caa98Sdjl return;
410*cb5caa98Sdjl
411*cb5caa98Sdjl SET_ACCESS_PTR;
412*cb5caa98Sdjl
413*cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_ACCESS_INFO, NSCD_LOG_LEVEL_DEBUG)
414*cb5caa98Sdjl (me, "data = %p, access->data = %p\n", data, access->data);
415*cb5caa98Sdjl ASSERT_ACCESS_DATA;
416*cb5caa98Sdjl
417*cb5caa98Sdjl assert(access->data_mutex != NULL);
418*cb5caa98Sdjl
419*cb5caa98Sdjl (void) mutex_unlock(access->data_mutex);
420*cb5caa98Sdjl _nscd_release(data);
421*cb5caa98Sdjl }
422*cb5caa98Sdjl
423*cb5caa98Sdjl /*
424*cb5caa98Sdjl * FUNCTION: _nscd_cond_wait
425*cb5caa98Sdjl *
426*cb5caa98Sdjl * Perform a condition wait with the cond_t and mutex_t associated
427*cb5caa98Sdjl * with data.
428*cb5caa98Sdjl */
429*cb5caa98Sdjl void
_nscd_cond_wait(nscd_acc_data_t * data,cond_t * cond)430*cb5caa98Sdjl _nscd_cond_wait(
431*cb5caa98Sdjl nscd_acc_data_t *data, cond_t *cond)
432*cb5caa98Sdjl {
433*cb5caa98Sdjl nscd_access_t *access;
434*cb5caa98Sdjl char *me = "_nscd_cond_wait";
435*cb5caa98Sdjl
436*cb5caa98Sdjl if (data == NULL)
437*cb5caa98Sdjl return;
438*cb5caa98Sdjl
439*cb5caa98Sdjl SET_ACCESS_PTR;
440*cb5caa98Sdjl
441*cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_ACCESS_INFO, NSCD_LOG_LEVEL_DEBUG)
442*cb5caa98Sdjl (me, "data = %p, access->data = %p\n", data, access->data);
443*cb5caa98Sdjl ASSERT_ACCESS_DATA;
444*cb5caa98Sdjl
445*cb5caa98Sdjl assert(access->data_cond != NULL && access->data_mutex != NULL);
446*cb5caa98Sdjl
447*cb5caa98Sdjl if (cond == NULL)
448*cb5caa98Sdjl (void) cond_wait(access->data_cond, access->data_mutex);
449*cb5caa98Sdjl else
450*cb5caa98Sdjl (void) cond_wait(cond, access->data_mutex);
451*cb5caa98Sdjl }
452*cb5caa98Sdjl
453*cb5caa98Sdjl /*
454*cb5caa98Sdjl * FUNCTION: _nscd_cond_signal
455*cb5caa98Sdjl *
456*cb5caa98Sdjl * Perform a condition signal with the cond_t associated with 'data'.
457*cb5caa98Sdjl */
458*cb5caa98Sdjl void
_nscd_cond_signal(nscd_acc_data_t * data)459*cb5caa98Sdjl _nscd_cond_signal(
460*cb5caa98Sdjl nscd_acc_data_t *data)
461*cb5caa98Sdjl {
462*cb5caa98Sdjl nscd_access_t *access;
463*cb5caa98Sdjl char *me = "_nscd_cond_signal";
464*cb5caa98Sdjl
465*cb5caa98Sdjl if (data == NULL)
466*cb5caa98Sdjl return;
467*cb5caa98Sdjl
468*cb5caa98Sdjl SET_ACCESS_PTR;
469*cb5caa98Sdjl
470*cb5caa98Sdjl _NSCD_LOG(NSCD_LOG_ACCESS_INFO, NSCD_LOG_LEVEL_DEBUG)
471*cb5caa98Sdjl (me, "data = %p, access->data = %p\n", data, access->data);
472*cb5caa98Sdjl ASSERT_ACCESS_DATA;
473*cb5caa98Sdjl
474*cb5caa98Sdjl assert(access->data_cond != NULL);
475*cb5caa98Sdjl
476*cb5caa98Sdjl (void) cond_signal(access->data_cond);
477*cb5caa98Sdjl }
478*cb5caa98Sdjl
479*cb5caa98Sdjl /*
480*cb5caa98Sdjl * FUNCTION: _nscd_alloc
481*cb5caa98Sdjl *
482*cb5caa98Sdjl * Allocate a piece of nscd memory. 'data_free'
483*cb5caa98Sdjl * is the function to invoke to free the data
484*cb5caa98Sdjl * stored in this memory, i.e., the desctrctor.
485*cb5caa98Sdjl * 'option' indicate whether a mutex or a
486*cb5caa98Sdjl * readers/writer (or both, or none) should also
487*cb5caa98Sdjl * be allocated.
488*cb5caa98Sdjl */
489*cb5caa98Sdjl nscd_acc_data_t *
_nscd_alloc(int type,size_t size,void (* data_free)(nscd_acc_data_t * data),int option)490*cb5caa98Sdjl _nscd_alloc(
491*cb5caa98Sdjl int type,
492*cb5caa98Sdjl size_t size,
493*cb5caa98Sdjl void (*data_free)(nscd_acc_data_t *data),
494*cb5caa98Sdjl int option)
495*cb5caa98Sdjl {
496*cb5caa98Sdjl nscd_access_t *access;
497*cb5caa98Sdjl nscd_acc_data_t *ptr;
498*cb5caa98Sdjl nscd_seq_num_t seq_num;
499*cb5caa98Sdjl rwlock_t *rwlock = NULL;
500*cb5caa98Sdjl mutex_t *mutex = NULL;
501*cb5caa98Sdjl cond_t *cond = NULL;
502*cb5caa98Sdjl
503*cb5caa98Sdjl if ((ptr = (nscd_acc_data_t *)calloc(1,
504*cb5caa98Sdjl size + sizeof_access)) == NULL)
505*cb5caa98Sdjl return (NULL);
506*cb5caa98Sdjl if (option & NSCD_ALLOC_MUTEX) {
507*cb5caa98Sdjl if ((mutex = (mutex_t *)calloc(1, sizeof (mutex_t))) ==
508*cb5caa98Sdjl NULL) {
509*cb5caa98Sdjl free(ptr);
510*cb5caa98Sdjl return (NULL);
511*cb5caa98Sdjl } else
512*cb5caa98Sdjl (void) mutex_init(mutex, USYNC_THREAD, NULL);
513*cb5caa98Sdjl }
514*cb5caa98Sdjl if (option & NSCD_ALLOC_RWLOCK) {
515*cb5caa98Sdjl if ((rwlock = (rwlock_t *)calloc(1, sizeof (rwlock_t))) ==
516*cb5caa98Sdjl NULL) {
517*cb5caa98Sdjl free(ptr);
518*cb5caa98Sdjl free(mutex);
519*cb5caa98Sdjl return (NULL);
520*cb5caa98Sdjl } else
521*cb5caa98Sdjl (void) rwlock_init(rwlock, USYNC_THREAD, NULL);
522*cb5caa98Sdjl }
523*cb5caa98Sdjl if (option & NSCD_ALLOC_COND) {
524*cb5caa98Sdjl if ((cond = (cond_t *)calloc(1, sizeof (cond_t))) ==
525*cb5caa98Sdjl NULL) {
526*cb5caa98Sdjl free(ptr);
527*cb5caa98Sdjl free(mutex);
528*cb5caa98Sdjl free(rwlock);
529*cb5caa98Sdjl return (NULL);
530*cb5caa98Sdjl } else
531*cb5caa98Sdjl (void) cond_init(cond, USYNC_THREAD, NULL);
532*cb5caa98Sdjl }
533*cb5caa98Sdjl
534*cb5caa98Sdjl /* get current sequence number */
535*cb5caa98Sdjl seq_num = _nscd_get_seq_num();
536*cb5caa98Sdjl
537*cb5caa98Sdjl access = (nscd_access_t *)ptr;
538*cb5caa98Sdjl access->data = (char *)ptr + sizeof_access;
539*cb5caa98Sdjl access->data_mutex = mutex;
540*cb5caa98Sdjl access->data_rwlock = rwlock;
541*cb5caa98Sdjl access->data_cond = cond;
542*cb5caa98Sdjl access->nUse = 0;
543*cb5caa98Sdjl access->delete = 0;
544*cb5caa98Sdjl access->type = type;
545*cb5caa98Sdjl access->free_func = data_free;
546*cb5caa98Sdjl access->seq_num = seq_num;
547*cb5caa98Sdjl
548*cb5caa98Sdjl /* add the address to the internal address database */
549*cb5caa98Sdjl if (_nscd_add_int_addr(access->data, type,
550*cb5caa98Sdjl seq_num) != NSCD_SUCCESS) {
551*cb5caa98Sdjl free(ptr);
552*cb5caa98Sdjl return (NULL);
553*cb5caa98Sdjl }
554*cb5caa98Sdjl
555*cb5caa98Sdjl return (access->data);
556*cb5caa98Sdjl }
557*cb5caa98Sdjl
558*cb5caa98Sdjl /*
559*cb5caa98Sdjl * FUNCTION: _nscd_free
560*cb5caa98Sdjl *
561*cb5caa98Sdjl * Free a piece of nscd memory.
562*cb5caa98Sdjl */
563*cb5caa98Sdjl static void
_nscd_free(nscd_acc_data_t * data)564*cb5caa98Sdjl _nscd_free(
565*cb5caa98Sdjl nscd_acc_data_t *data)
566*cb5caa98Sdjl {
567*cb5caa98Sdjl nscd_access_t *access;
568*cb5caa98Sdjl
569*cb5caa98Sdjl if (data == NULL)
570*cb5caa98Sdjl return;
571*cb5caa98Sdjl
572*cb5caa98Sdjl SET_ACCESS_PTR;
573*cb5caa98Sdjl ASSERT_ACCESS_DATA;
574*cb5caa98Sdjl
575*cb5caa98Sdjl /* remove the address from the internal address database */
576*cb5caa98Sdjl _nscd_del_int_addr(access->data, access->seq_num);
577*cb5caa98Sdjl
578*cb5caa98Sdjl if (access->data_mutex)
579*cb5caa98Sdjl free(access->data_mutex);
580*cb5caa98Sdjl if (access->data_rwlock)
581*cb5caa98Sdjl free(access->data_rwlock);
582*cb5caa98Sdjl if (access->data_cond)
583*cb5caa98Sdjl free(access->data_cond);
584*cb5caa98Sdjl
585*cb5caa98Sdjl (void) memset(access, 0, sizeof (*access));
586*cb5caa98Sdjl
587*cb5caa98Sdjl free(access);
588*cb5caa98Sdjl }
589