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 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 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 * 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 * 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 * 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 * 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 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 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 * 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 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 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 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 * 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 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