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