1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #pragma ident "%Z%%M% %I% %E% SMI" 27 28 #include <stdio.h> 29 #include <stdlib.h> 30 #include <assert.h> 31 #include <string.h> 32 #include "nscd_switch.h" 33 #include "nscd_log.h" 34 35 /* 36 * nscd_nsw_state_t list for each nss database. Protected 37 * by the readers/writer lock nscd_nsw_state_base_lock. 38 */ 39 nscd_nsw_state_base_t **nscd_nsw_state_base; 40 static rwlock_t nscd_nsw_state_base_lock = DEFAULTRWLOCK; 41 42 static void 43 _nscd_free_nsw_state( 44 nscd_nsw_state_t *s) 45 { 46 47 int i; 48 char *me = "_nscd_free_nsw_state"; 49 50 _NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG) 51 (me, "freeing nsw state = %p\n", s); 52 53 if (s == NULL) 54 return; 55 56 if (s->nsw_cfg_p != NULL) 57 /* 58 * an nsw state without base does not reference 59 * count the nsw config data (ie not using a 60 * shared one), so the one created for it should 61 * be freed 62 */ 63 if ((*s->nsw_cfg_p)->nobase != 1) 64 _nscd_release((nscd_acc_data_t *)s->nsw_cfg_p); 65 else 66 _nscd_free_nsw_config(*s->nsw_cfg_p); 67 68 if (s->be_db_pp != NULL) { 69 for (i = 0; i < s->max_src; i++) { 70 if (s->be_db_pp[i] == NULL) 71 continue; 72 _nscd_release((nscd_acc_data_t *)s->be_db_pp[i]); 73 _NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG) 74 (me, "release db be ptr %p\n", s->be_db_pp[i]); 75 } 76 free(s->be_db_pp); 77 } 78 79 if (s->be != NULL) { 80 for (i = 0; i < s->max_src; i++) { 81 if (s->be[i] == NULL) 82 continue; 83 if (s->getent == 1) 84 (void) NSS_INVOKE_DBOP(s->be[i], 85 NSS_DBOP_ENDENT, 0); 86 (void) NSS_INVOKE_DBOP(s->be[i], 87 NSS_DBOP_DESTRUCTOR, 0); 88 } 89 free(s->be); 90 } 91 92 s->base = NULL; 93 94 _NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG) 95 (me, "nsw state %p freed \n", s); 96 97 free(s); 98 } 99 100 static void 101 _nscd_free_nsw_state_base( 102 nscd_acc_data_t *data) 103 { 104 nscd_nsw_state_base_t *base = (nscd_nsw_state_base_t *)data; 105 nscd_nsw_state_t *s, *ts; 106 int i; 107 char *me = "_nscd_free_nsw_state_base"; 108 109 _NSCD_LOG(NSCD_LOG_NSW_STATE | NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG) 110 (me, "freeing db state base %p\n", base); 111 112 if (base == NULL) 113 return; 114 115 for (i = 0; i < 2; i++) { 116 if (i == 1) 117 s = base->nsw_state.first; 118 else 119 s = base->nsw_state_thr.first; 120 121 while (s != NULL) { 122 ts = s->next; 123 _nscd_free_nsw_state(s); 124 s = ts; 125 } 126 } 127 128 _NSCD_LOG(NSCD_LOG_NSW_STATE | NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG) 129 (me, "nsw state base %p freed \n", base); 130 } 131 132 void 133 _nscd_free_all_nsw_state_base() 134 { 135 nscd_nsw_state_base_t *base; 136 int i; 137 char *me = "_nscd_free_all_nsw_state_base"; 138 139 _NSCD_LOG(NSCD_LOG_NSW_STATE | NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG) 140 (me, "freeing all db state base\n"); 141 142 (void) rw_wrlock(&nscd_nsw_state_base_lock); 143 for (i = 0; i < NSCD_NUM_DB; i++) { 144 145 base = nscd_nsw_state_base[i]; 146 _NSCD_LOG(NSCD_LOG_NSW_STATE | NSCD_LOG_CONFIG, 147 NSCD_LOG_LEVEL_DEBUG) 148 (me, "freeing db state base (%d) %p \n", i, base); 149 150 if (base == NULL) 151 continue; 152 153 nscd_nsw_state_base[i] = (nscd_nsw_state_base_t *) 154 _nscd_set((nscd_acc_data_t *)base, NULL); 155 } 156 (void) rw_unlock(&nscd_nsw_state_base_lock); 157 } 158 159 static nscd_nsw_state_t * 160 _nscd_create_nsw_state( 161 nscd_nsw_params_t *params) 162 { 163 nscd_nsw_state_t *s; 164 nscd_nsw_config_t *nsw_cfg; 165 nscd_db_t **be_db_p, *be_db; 166 int i, nobe = 1; 167 char *me = "_nscd_create_nsw_state"; 168 169 170 _NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG) 171 (me, "creating nsw state...\n"); 172 173 s = calloc(1, sizeof (nscd_nsw_state_t)); 174 if (s == NULL) { 175 if ((*s->nsw_cfg_p)->nobase != 1) 176 _nscd_release((nscd_acc_data_t *)params->nswcfg); 177 _NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_ERROR) 178 (me, "not able to allocate a nsw state\n"); 179 return (NULL); 180 } else 181 _NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG) 182 (me, "nsw state %p allocated\n", s); 183 184 s->dbi = params->dbi; 185 s->next = NULL; 186 187 nsw_cfg = *params->nswcfg; 188 189 s->nsw_cfg_p = params->nswcfg; 190 s->config = nsw_cfg->nsw_config; 191 s->max_src = nsw_cfg->max_src; 192 s->p = params->p; 193 194 s->be = calloc(s->max_src, sizeof (nss_backend_t **)); 195 if (s->be == NULL) { 196 _NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_ERROR) 197 (me, "not able to allocate s->be\n"); 198 199 _nscd_free_nsw_state(s); 200 return (NULL); 201 } else { 202 _NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG) 203 (me, "db be array %p allocated\n", s->be); 204 } 205 206 s->be_db_pp = calloc(s->max_src, sizeof (nscd_db_t ***)); 207 if (s->be_db_pp == NULL) { 208 _NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_ERROR) 209 (me, "not able to allocate s->be_db_pp\n"); 210 _nscd_free_nsw_state(s); 211 return (NULL); 212 } else { 213 _NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG) 214 (me, "be_db_pp array %p allocated\n", s->be_db_pp); 215 } 216 217 /* create the source:database backends */ 218 for (i = 0; i < s->max_src; i++) { 219 nss_backend_t *be; 220 int srci; 221 char *srcn; 222 const char *dbn; 223 struct __nsw_lookup_v1 *lkp; 224 const nscd_db_entry_t *dbe; 225 nscd_be_info_t *be_info; 226 227 if (i == 0) 228 lkp = s->config->lookups; 229 else 230 lkp = lkp->next; 231 if (lkp == NULL) { 232 _NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_ERROR) 233 (me, "error: lkp is NULL\n"); 234 _nscd_free_nsw_state(s); 235 return (NULL); 236 } 237 238 srci = nsw_cfg->src_idx[i]; 239 srcn = lkp->service_name; 240 _NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG) 241 (me, "source name = %s, index = %d\n", srcn, srci); 242 243 be_db_p = (nscd_db_t **)_nscd_get( 244 (nscd_acc_data_t *)nscd_src_backend_db[srci]); 245 if (be_db_p == NULL) { 246 _nscd_free_nsw_state(s); 247 return (NULL); 248 } 249 be_db = *be_db_p; 250 s->be_db_pp[i] = be_db_p; 251 _NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG) 252 (me, "be db ptr array %p referenced\n", be_db_p); 253 254 be_info = NULL; 255 be = NULL; 256 dbn = params->p.name; 257 dbe = _nscd_get_db_entry(be_db, NSCD_DATA_BACKEND_INFO, 258 (const char *)dbn, NSCD_GET_FIRST_DB_ENTRY, 0); 259 if (dbe != NULL) 260 be_info = (nscd_be_info_t *)*(dbe->data_array); 261 262 if (be_info == NULL || be_info->be_constr == NULL) { 263 _NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG) 264 (me, "no backend info or be_constr is NULL " 265 "for <%s : %s>\n", NSCD_NSW_SRC_NAME(srci), 266 dbn); 267 } else 268 be = (be_info->be_constr)(dbn, 269 NSCD_NSW_SRC_NAME(srci), 0); 270 271 if (be == NULL) { 272 _NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_ERROR) 273 (me, "not able to init be for <%s : %s>\n", 274 NSCD_NSW_SRC_NAME(srci), dbn); 275 276 _NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG) 277 (me, "releasing db be ptr %p\n", be_db_p); 278 279 _nscd_release((nscd_acc_data_t *)be_db_p); 280 s->be_db_pp[i] = NULL; 281 282 continue; 283 } 284 285 s->be[i] = be; 286 nobe = 0; 287 } 288 289 if (nobe == 1) { 290 _NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG) 291 (me, "NO backend found, returning NULL\n"); 292 293 _nscd_free_nsw_state(s); 294 return (NULL); 295 } 296 297 return (s); 298 } 299 300 static nscd_rc_t 301 _get_nsw_state_int( 302 nss_db_root_t *rootp, 303 nscd_nsw_params_t *params, 304 thread_t *tid) 305 { 306 307 nscd_nsw_state_t *ret = NULL; 308 nscd_nsw_config_t **nswcfg; 309 nscd_nsw_state_base_t *base; 310 nscd_state_ctrl_t *ctrl_p; 311 int thread_only = 0, wait_cond = 0; 312 char *me = "_get_nsw_state_int"; 313 int dbi; 314 nscd_rc_t rc; 315 316 dbi = params->dbi; 317 318 /* 319 * no nsw state will be reused, if asked to use 320 * default config. So create the new structures 321 * used by the switch engine and the new nsw state 322 */ 323 if (params->p.flags & NSS_USE_DEFAULT_CONFIG) { 324 rc = _nscd_create_sw_struct(dbi, (char *)params->p.name, 325 (char *)params->p.default_config, NULL, params); 326 if (rc != NSCD_SUCCESS) 327 return (rc); 328 329 _NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG) 330 (me, "no base nsw config created for %s (sources: %s)\n", 331 params->p.name, params->p.default_config); 332 333 ret = _nscd_create_nsw_state(params); 334 if (ret == NULL) 335 return (NSCD_CREATE_NSW_STATE_FAILED); 336 rootp->s = (struct nss_db_state *)ret; 337 return (NSCD_SUCCESS); 338 } 339 340 /* 341 * if getting a nsw state for a request from the compat 342 * backend, create the new switch structures if this 343 * is the first time around for a passwd, shadow, group, 344 * audit_user, or user_attr database 345 */ 346 if (params->compati != -1) { 347 348 nscd_nsw_config_t **nswcfg1; 349 int i = params->compati; 350 351 nswcfg = (nscd_nsw_config_t **)_nscd_get( 352 (nscd_acc_data_t *)nscd_nsw_config[i]); 353 354 /* 355 * if nsw data structures not created yet, get the 356 * config string from the passwd_compat or 357 * group_compat DB and create the structures 358 */ 359 if (nswcfg == NULL) { 360 nswcfg1 = (nscd_nsw_config_t **)_nscd_get( 361 (nscd_acc_data_t *)nscd_nsw_config[params->cfgdbi]); 362 if (nswcfg1 == NULL) { 363 _NSCD_LOG(NSCD_LOG_NSW_STATE, 364 NSCD_LOG_LEVEL_ERROR) 365 (me, "no nsw config for %s\n", 366 params->p.name); 367 return (NSCD_CREATE_NSW_STATE_FAILED); 368 } 369 370 rc = _nscd_create_sw_struct(i, params->p.name, 371 (*nswcfg1)->nsw_cfg_str, NULL, params); 372 _nscd_release((nscd_acc_data_t *)nswcfg1); 373 if (rc != NSCD_SUCCESS) 374 return (rc); 375 376 _NSCD_LOG(NSCD_LOG_NSW_STATE, 377 NSCD_LOG_LEVEL_DEBUG) 378 (me, "nsw config created for %s (%s)\n", 379 params->p.name, (*nswcfg1)->nsw_cfg_str); 380 } else 381 _nscd_release((nscd_acc_data_t *)nswcfg); 382 } 383 384 (void) rw_rdlock(&nscd_nsw_state_base_lock); 385 base = nscd_nsw_state_base[dbi]; 386 (void) rw_unlock(&nscd_nsw_state_base_lock); 387 if (base == NULL) 388 assert(base != NULL); 389 390 /* 391 * If list is not empty, return the first one on list. 392 * Otherwise, create and return a new db state if the 393 * limit is not reached. if reacehed, wait for the 'one 394 * is available' signal. 395 */ 396 assert(base == (nscd_nsw_state_base_t *)_nscd_mutex_lock( 397 (nscd_acc_data_t *)base)); 398 399 if (tid == NULL) { 400 ctrl_p = &base->nsw_state; 401 } else { 402 thread_only = 1; 403 ctrl_p = &base->nsw_state_thr; 404 405 _NSCD_LOG_IF(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG) { 406 _nscd_logit(me, "per thread nsw state info: \n"); 407 _nscd_logit(me, "tid = %d\n", *tid); 408 _nscd_logit(me, "tid in base = %d\n", base->tid); 409 _nscd_logit(me, "number of free nsw_state = %d\n", 410 ctrl_p->free); 411 _nscd_logit(me, "number of nsw state allocated = %d\n", 412 ctrl_p->allocated); 413 _nscd_logit(me, "first nsw state on list = %p\n", 414 ctrl_p->first); 415 _nscd_logit(me, "number of waiter = %d\n", 416 ctrl_p->waiter); 417 } 418 } 419 420 if (ctrl_p->first == NULL && ctrl_p->allocated == ctrl_p->max) 421 wait_cond = 1; 422 else if (thread_only && base->used_by_thr && base->tid != *tid) 423 wait_cond = 1; 424 425 if (wait_cond) { 426 427 ctrl_p->waiter++; 428 429 while (wait_cond) { 430 if (!thread_only) 431 _NSCD_LOG(NSCD_LOG_NSW_STATE, 432 NSCD_LOG_LEVEL_DEBUG) 433 (me, "waiting for nsw state signal\n"); 434 else 435 _NSCD_LOG(NSCD_LOG_NSW_STATE, 436 NSCD_LOG_LEVEL_DEBUG) 437 (me, "waiting for per thread " 438 "nsw state signal\n"); 439 440 if (thread_only) { 441 _nscd_cond_wait((nscd_acc_data_t *)base, 442 &base->thr_cond); 443 444 if (base->used_by_thr == 0 && 445 ctrl_p->first != NULL) 446 wait_cond = 0; 447 } else { 448 _nscd_cond_wait((nscd_acc_data_t *)base, NULL); 449 450 if (ctrl_p->first != NULL) 451 wait_cond = 0; 452 } 453 454 if (!thread_only) 455 _NSCD_LOG(NSCD_LOG_NSW_STATE, 456 NSCD_LOG_LEVEL_DEBUG) 457 (me, "woke from cond wait ...wait_cond = %d\n", 458 wait_cond); 459 else 460 461 _NSCD_LOG(NSCD_LOG_NSW_STATE, 462 NSCD_LOG_LEVEL_DEBUG) 463 (me, "woke from cond wait (per thread) " 464 "...wait_cond = %d\n", wait_cond); 465 466 } 467 468 ctrl_p->waiter--; 469 } 470 471 if (ctrl_p->first == NULL) { 472 int geti; 473 474 /* 475 * for lookup calls from the compat backend 476 * uses the switch policy for passwd_compat 477 * or group_compat 478 */ 479 if (params->compati != -1) 480 geti = params->compati; 481 else 482 geti = params->dbi; 483 484 params->nswcfg = (nscd_nsw_config_t **)_nscd_get( 485 (nscd_acc_data_t *)nscd_nsw_config[geti]); 486 _NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG) 487 (me, "got a nsw config %p for index %d\n", 488 params->nswcfg, geti); 489 490 ctrl_p->first = _nscd_create_nsw_state(params); 491 if (ctrl_p->first != NULL) { 492 ctrl_p->first->base = base; 493 494 if (tid == NULL) { 495 _NSCD_LOG(NSCD_LOG_NSW_STATE, 496 NSCD_LOG_LEVEL_DEBUG) 497 (me, "got a new nsw_state %p\n", ctrl_p->first); 498 } else { 499 _NSCD_LOG(NSCD_LOG_NSW_STATE, 500 NSCD_LOG_LEVEL_DEBUG) 501 (me, "got a new per thread nsw_state %p\n", 502 ctrl_p->first); 503 } 504 ctrl_p->allocated++; 505 ctrl_p->free++; 506 } else { 507 _NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_ERROR) 508 (me, "error: unable to obtain a nsw state\n"); 509 _nscd_mutex_unlock((nscd_acc_data_t *)base); 510 return (NSCD_CREATE_NSW_STATE_FAILED); 511 } 512 } 513 514 ret = ctrl_p->first; 515 ctrl_p->first = ret->next; 516 ret->next = NULL; 517 ctrl_p->free--; 518 if (thread_only) { 519 base->tid = *tid; 520 base->used_by_thr = 1; 521 522 _NSCD_LOG_IF(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG) { 523 _nscd_logit(me, "\t\t\tgot a per thread nsw " 524 "state %p: \n", ret); 525 _nscd_logit(me, "tid = %d\n", *tid); 526 _nscd_logit(me, "tid in base = %d\n", base->tid); 527 _nscd_logit(me, "number of free nsw_state = %d\n", 528 ctrl_p->free); 529 _nscd_logit(me, "number od nsw state allocated = %d\n", 530 ctrl_p->allocated); 531 _nscd_logit(me, "first nsw state on list = %p\n", 532 ctrl_p->first); 533 _nscd_logit(me, "number of waiter = %d\n", 534 ctrl_p->waiter); 535 } 536 } 537 else 538 _NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG) 539 (me, "got old nsw state %p\n", ret); 540 541 _nscd_mutex_unlock((nscd_acc_data_t *)base); 542 543 rootp->s = (struct nss_db_state *)ret; 544 545 return (NSCD_SUCCESS); 546 } 547 548 nscd_rc_t 549 _nscd_get_nsw_state( 550 nss_db_root_t *rootp, 551 nscd_nsw_params_t *params) 552 { 553 return (_get_nsw_state_int(rootp, params, NULL)); 554 } 555 556 nscd_rc_t 557 _nscd_get_nsw_state_thread( 558 nss_db_root_t *rootp, 559 nscd_nsw_params_t *params) 560 { 561 thread_t tid = thr_self(); 562 return (_get_nsw_state_int(rootp, params, &tid)); 563 } 564 565 566 static void 567 _put_nsw_state_int( 568 nscd_nsw_state_t *s, 569 thread_t *tid) 570 { 571 572 nscd_nsw_state_base_t *base; 573 nscd_state_ctrl_t *ctrl_p; 574 int thread_only = 0; 575 char *me = "_put_nsw_state_int"; 576 577 _NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG) 578 (me, "put back a nsw state\n"); 579 580 if (s == NULL) { 581 _NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG) 582 (me, "nsw state is NULL, nothing to put back\n"); 583 return; 584 } 585 586 /* 587 * no need to put back if the nsw state is not on any base 588 * but need to free the resources used 589 */ 590 if ((*s->nsw_cfg_p)->nobase == 1) { 591 _NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG) 592 (me, "no base nsw state, freeing resources ...\n"); 593 594 _nscd_free_nsw_state(s); 595 return; 596 } 597 598 if (tid != NULL) 599 thread_only = 1; 600 601 base = s->base; 602 603 if (_nscd_mutex_lock((nscd_acc_data_t *)base) == NULL) { 604 /* base has been freed, free this db state */ 605 _NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG) 606 (me, "nsw state base has been freed, freeing %p\n", s); 607 _nscd_free_nsw_state(s); 608 return; 609 } 610 611 if (thread_only) 612 ctrl_p = &base->nsw_state_thr; 613 else 614 ctrl_p = &base->nsw_state; 615 616 _NSCD_LOG_IF(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG) { 617 _nscd_logit(me, "before returning the nsw state: \n"); 618 _nscd_logit(me, "tid = %d\n", (tid == NULL) ? -1 : *tid); 619 _nscd_logit(me, "tid in base = %d\n", base->tid); 620 _nscd_logit(me, "number of free nsw_state = %d\n", 621 ctrl_p->free); 622 _nscd_logit(me, "number od nsw state allocated = %d\n", 623 ctrl_p->allocated); 624 _nscd_logit(me, "first nsw state on list = %p\n", 625 ctrl_p->first); 626 _nscd_logit(me, "number of waiter = %d\n", 627 ctrl_p->waiter); 628 } 629 630 if (ctrl_p->first != NULL) { 631 s->next = ctrl_p->first; 632 ctrl_p->first = s; 633 } else { 634 ctrl_p->first = s; 635 s->next = NULL; 636 } 637 ctrl_p->free++; 638 639 _NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG) 640 (me, "signaling waiter thread_only = %d..\n", thread_only); 641 642 if (thread_only && ctrl_p->free == ctrl_p->allocated) { 643 assert(ctrl_p->first != NULL); 644 base->used_by_thr = 0; 645 if (ctrl_p->waiter > 0) { 646 (void) cond_signal(&base->thr_cond); 647 } 648 } 649 650 if (!thread_only && ctrl_p->waiter > 0) { 651 652 _nscd_cond_signal((nscd_acc_data_t *)base); 653 } 654 655 _NSCD_LOG_IF(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG) { 656 _nscd_logit(me, "after the nsw state is returned: \n"); 657 _nscd_logit(me, "tid = %d\n", (tid == NULL) ? -1 : *tid); 658 _nscd_logit(me, "tid in base = %d\n", base->tid); 659 _nscd_logit(me, "number of free nsw_state = %d\n", 660 ctrl_p->free); 661 _nscd_logit(me, "number od nsw state allocated = %d\n", 662 ctrl_p->allocated); 663 _nscd_logit(me, "first nsw state on list = %p\n", 664 ctrl_p->first); 665 _nscd_logit(me, "tnumber of waiter = %d\n", 666 ctrl_p->waiter); 667 } 668 669 _NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG) 670 (me, "done putting back nsw state %p, thread_only = %d\n", 671 s, thread_only); 672 673 _nscd_mutex_unlock((nscd_acc_data_t *)base); 674 675 } 676 677 void 678 _nscd_put_nsw_state( 679 nscd_nsw_state_t *s) 680 { 681 _put_nsw_state_int(s, NULL); 682 } 683 684 void 685 _nscd_put_nsw_state_thread( 686 nscd_nsw_state_t *s) 687 { 688 thread_t tid = thr_self(); 689 _put_nsw_state_int(s, &tid); 690 } 691 692 nscd_rc_t 693 _nscd_init_nsw_state_base( 694 int dbi, 695 int lock) 696 { 697 nscd_nsw_state_base_t *base = NULL; 698 char *me = "_nscd_init_nsw_state_base"; 699 700 if (lock) 701 (void) rw_rdlock(&nscd_nsw_state_base_lock); 702 703 base = (nscd_nsw_state_base_t *)_nscd_alloc( 704 NSCD_DATA_NSW_STATE_BASE, 705 sizeof (nscd_nsw_state_base_t), 706 _nscd_free_nsw_state_base, 707 NSCD_ALLOC_MUTEX | NSCD_ALLOC_COND); 708 709 if (base == NULL) { 710 _NSCD_LOG(NSCD_LOG_NSW_STATE | NSCD_LOG_CONFIG, 711 NSCD_LOG_LEVEL_ERROR) 712 (me, "not able to allocate a nsw state base\n"); 713 if (lock) 714 (void) rw_unlock(&nscd_nsw_state_base_lock); 715 return (NSCD_NO_MEMORY); 716 } 717 _NSCD_LOG(NSCD_LOG_NSW_STATE | NSCD_LOG_CONFIG, 718 NSCD_LOG_LEVEL_DEBUG) 719 (me, "nsw state base %p allocated\n", base); 720 721 /* 722 * initialize and activate the new nss_nsw_state base 723 */ 724 base->dbi = dbi; 725 base->nsw_state.max = NSCD_SW_CFG(dbi).max_nsw_state_per_db; 726 base->nsw_state_thr.max = NSCD_SW_CFG(dbi).max_nsw_state_per_thread; 727 728 nscd_nsw_state_base[dbi] = (nscd_nsw_state_base_t *)_nscd_set( 729 (nscd_acc_data_t *)nscd_nsw_state_base[dbi], 730 (nscd_acc_data_t *)base); 731 732 if (lock) 733 (void) rw_unlock(&nscd_nsw_state_base_lock); 734 735 return (NSCD_SUCCESS); 736 } 737 738 nscd_rc_t 739 _nscd_init_all_nsw_state_base() 740 { 741 int i; 742 nscd_rc_t rc; 743 char *me = "_nscd_init_all_nsw_state_base"; 744 745 (void) rw_rdlock(&nscd_nsw_state_base_lock); 746 747 for (i = 0; i < NSCD_NUM_DB; i++) { 748 749 rc = _nscd_init_nsw_state_base(i, 0); 750 751 if (rc != NSCD_SUCCESS) { 752 _NSCD_LOG(NSCD_LOG_NSW_STATE | NSCD_LOG_CONFIG, 753 NSCD_LOG_LEVEL_ERROR) 754 (me, "not able to initialize a nsw db state " 755 "base (%d)\n", i); 756 757 (void) rw_unlock(&nscd_nsw_state_base_lock); 758 return (rc); 759 } 760 } 761 _NSCD_LOG(NSCD_LOG_NSW_STATE | NSCD_LOG_CONFIG, 762 NSCD_LOG_LEVEL_DEBUG) 763 (me, "all nsw state base initialized\n"); 764 765 (void) rw_unlock(&nscd_nsw_state_base_lock); 766 767 return (NSCD_SUCCESS); 768 } 769 770 nscd_rc_t 771 _nscd_alloc_nsw_state_base() 772 { 773 774 (void) rw_rdlock(&nscd_nsw_state_base_lock); 775 776 nscd_nsw_state_base = calloc(NSCD_NUM_DB, 777 sizeof (nscd_nsw_state_base_t *)); 778 if (nscd_nsw_state_base == NULL) { 779 (void) rw_unlock(&nscd_nsw_state_base_lock); 780 return (NSCD_NO_MEMORY); 781 } 782 783 (void) rw_rdlock(&nscd_nsw_state_base_lock); 784 785 return (NSCD_SUCCESS); 786 } 787