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, -1, (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 dbi = i; 352 353 nswcfg = (nscd_nsw_config_t **)_nscd_get( 354 (nscd_acc_data_t *)nscd_nsw_config[i]); 355 356 /* 357 * if nsw data structures not created yet, get the 358 * config string from the passwd_compat or 359 * group_compat DB and create the structures 360 */ 361 if (nswcfg == NULL) { 362 nswcfg1 = (nscd_nsw_config_t **)_nscd_get( 363 (nscd_acc_data_t *)nscd_nsw_config[params->cfgdbi]); 364 if (nswcfg1 == NULL) { 365 _NSCD_LOG(NSCD_LOG_NSW_STATE, 366 NSCD_LOG_LEVEL_ERROR) 367 (me, "no nsw config for %s\n", 368 params->p.name); 369 return (NSCD_CREATE_NSW_STATE_FAILED); 370 } 371 372 rc = _nscd_create_sw_struct(i, params->cfgdbi, 373 params->p.name, (*nswcfg1)->nsw_cfg_str, 374 NULL, params); 375 _nscd_release((nscd_acc_data_t *)nswcfg1); 376 if (rc != NSCD_SUCCESS) 377 return (rc); 378 379 _NSCD_LOG(NSCD_LOG_NSW_STATE, 380 NSCD_LOG_LEVEL_DEBUG) 381 (me, "nsw config created for %s (%s)\n", 382 params->p.name, (*nswcfg1)->nsw_cfg_str); 383 } else 384 _nscd_release((nscd_acc_data_t *)nswcfg); 385 } 386 387 (void) rw_rdlock(&nscd_nsw_state_base_lock); 388 base = nscd_nsw_state_base[dbi]; 389 (void) rw_unlock(&nscd_nsw_state_base_lock); 390 if (base == NULL) 391 assert(base != NULL); 392 393 /* 394 * If list is not empty, return the first one on list. 395 * Otherwise, create and return a new db state if the 396 * limit is not reached. if reacehed, wait for the 'one 397 * is available' signal. 398 */ 399 assert(base == (nscd_nsw_state_base_t *)_nscd_mutex_lock( 400 (nscd_acc_data_t *)base)); 401 402 if (tid == NULL) { 403 ctrl_p = &base->nsw_state; 404 } else { 405 thread_only = 1; 406 ctrl_p = &base->nsw_state_thr; 407 408 _NSCD_LOG_IF(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG) { 409 _nscd_logit(me, "per thread nsw state info: \n"); 410 _nscd_logit(me, "tid = %d\n", *tid); 411 _nscd_logit(me, "tid in base = %d\n", base->tid); 412 _nscd_logit(me, "number of free nsw_state = %d\n", 413 ctrl_p->free); 414 _nscd_logit(me, "number of nsw state allocated = %d\n", 415 ctrl_p->allocated); 416 _nscd_logit(me, "first nsw state on list = %p\n", 417 ctrl_p->first); 418 _nscd_logit(me, "number of waiter = %d\n", 419 ctrl_p->waiter); 420 } 421 } 422 423 if (ctrl_p->first == NULL && ctrl_p->allocated == ctrl_p->max) 424 wait_cond = 1; 425 else if (thread_only && base->used_by_thr && base->tid != *tid) 426 wait_cond = 1; 427 428 if (wait_cond) { 429 430 ctrl_p->waiter++; 431 432 while (wait_cond) { 433 if (!thread_only) 434 _NSCD_LOG(NSCD_LOG_NSW_STATE, 435 NSCD_LOG_LEVEL_DEBUG) 436 (me, "waiting for nsw state signal\n"); 437 else 438 _NSCD_LOG(NSCD_LOG_NSW_STATE, 439 NSCD_LOG_LEVEL_DEBUG) 440 (me, "waiting for per thread " 441 "nsw state signal\n"); 442 443 if (thread_only) { 444 _nscd_cond_wait((nscd_acc_data_t *)base, 445 &base->thr_cond); 446 447 if (base->used_by_thr == 0 && 448 ctrl_p->first != NULL) 449 wait_cond = 0; 450 } else { 451 _nscd_cond_wait((nscd_acc_data_t *)base, NULL); 452 453 if (ctrl_p->first != NULL) 454 wait_cond = 0; 455 } 456 457 if (!thread_only) 458 _NSCD_LOG(NSCD_LOG_NSW_STATE, 459 NSCD_LOG_LEVEL_DEBUG) 460 (me, "woke from cond wait ...wait_cond = %d\n", 461 wait_cond); 462 else 463 464 _NSCD_LOG(NSCD_LOG_NSW_STATE, 465 NSCD_LOG_LEVEL_DEBUG) 466 (me, "woke from cond wait (per thread) " 467 "...wait_cond = %d\n", wait_cond); 468 469 } 470 471 ctrl_p->waiter--; 472 } 473 474 if (ctrl_p->first == NULL) { 475 int geti; 476 477 /* 478 * for lookup calls from the compat backend 479 * uses the switch policy for passwd_compat 480 * or group_compat 481 */ 482 if (params->compati != -1) 483 geti = params->compati; 484 else 485 geti = params->dbi; 486 487 params->nswcfg = (nscd_nsw_config_t **)_nscd_get( 488 (nscd_acc_data_t *)nscd_nsw_config[geti]); 489 _NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG) 490 (me, "got a nsw config %p for index %d\n", 491 params->nswcfg, geti); 492 493 ctrl_p->first = _nscd_create_nsw_state(params); 494 if (ctrl_p->first != NULL) { 495 ctrl_p->first->base = base; 496 497 if (tid == NULL) { 498 _NSCD_LOG(NSCD_LOG_NSW_STATE, 499 NSCD_LOG_LEVEL_DEBUG) 500 (me, "got a new nsw_state %p\n", ctrl_p->first); 501 } else { 502 _NSCD_LOG(NSCD_LOG_NSW_STATE, 503 NSCD_LOG_LEVEL_DEBUG) 504 (me, "got a new per thread nsw_state %p\n", 505 ctrl_p->first); 506 } 507 ctrl_p->allocated++; 508 ctrl_p->free++; 509 } else { 510 _NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_ERROR) 511 (me, "error: unable to obtain a nsw state\n"); 512 _nscd_mutex_unlock((nscd_acc_data_t *)base); 513 return (NSCD_CREATE_NSW_STATE_FAILED); 514 } 515 } 516 517 ret = ctrl_p->first; 518 ctrl_p->first = ret->next; 519 ret->next = NULL; 520 ctrl_p->free--; 521 if (thread_only) { 522 base->tid = *tid; 523 base->used_by_thr = 1; 524 525 _NSCD_LOG_IF(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG) { 526 _nscd_logit(me, "\t\t\tgot a per thread nsw " 527 "state %p: \n", ret); 528 _nscd_logit(me, "tid = %d\n", *tid); 529 _nscd_logit(me, "tid in base = %d\n", base->tid); 530 _nscd_logit(me, "number of free nsw_state = %d\n", 531 ctrl_p->free); 532 _nscd_logit(me, "number od nsw state allocated = %d\n", 533 ctrl_p->allocated); 534 _nscd_logit(me, "first nsw state on list = %p\n", 535 ctrl_p->first); 536 _nscd_logit(me, "number of waiter = %d\n", 537 ctrl_p->waiter); 538 } 539 } 540 else 541 _NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG) 542 (me, "got old nsw state %p\n", ret); 543 544 _nscd_mutex_unlock((nscd_acc_data_t *)base); 545 546 rootp->s = (struct nss_db_state *)ret; 547 548 return (NSCD_SUCCESS); 549 } 550 551 nscd_rc_t 552 _nscd_get_nsw_state( 553 nss_db_root_t *rootp, 554 nscd_nsw_params_t *params) 555 { 556 return (_get_nsw_state_int(rootp, params, NULL)); 557 } 558 559 nscd_rc_t 560 _nscd_get_nsw_state_thread( 561 nss_db_root_t *rootp, 562 nscd_nsw_params_t *params) 563 { 564 thread_t tid = thr_self(); 565 return (_get_nsw_state_int(rootp, params, &tid)); 566 } 567 568 569 static void 570 _put_nsw_state_int( 571 nscd_nsw_state_t *s, 572 thread_t *tid) 573 { 574 575 nscd_nsw_state_base_t *base; 576 nscd_state_ctrl_t *ctrl_p; 577 int thread_only = 0; 578 char *me = "_put_nsw_state_int"; 579 580 _NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG) 581 (me, "put back a nsw state\n"); 582 583 if (s == NULL) { 584 _NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG) 585 (me, "nsw state is NULL, nothing to put back\n"); 586 return; 587 } 588 589 /* 590 * no need to put back if the nsw state is not on any base 591 * but need to free the resources used 592 */ 593 if ((*s->nsw_cfg_p)->nobase == 1) { 594 _NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG) 595 (me, "no base nsw state, freeing resources ...\n"); 596 597 _nscd_free_nsw_state(s); 598 return; 599 } 600 601 if (tid != NULL) 602 thread_only = 1; 603 604 base = s->base; 605 606 if (_nscd_mutex_lock((nscd_acc_data_t *)base) == NULL) { 607 /* base has been freed, free this db state */ 608 _NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG) 609 (me, "nsw state base has been freed, freeing %p\n", s); 610 _nscd_free_nsw_state(s); 611 return; 612 } 613 614 if (thread_only) 615 ctrl_p = &base->nsw_state_thr; 616 else 617 ctrl_p = &base->nsw_state; 618 619 _NSCD_LOG_IF(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG) { 620 _nscd_logit(me, "before returning the nsw state: \n"); 621 _nscd_logit(me, "tid = %d\n", (tid == NULL) ? -1 : *tid); 622 _nscd_logit(me, "tid in base = %d\n", base->tid); 623 _nscd_logit(me, "number of free nsw_state = %d\n", 624 ctrl_p->free); 625 _nscd_logit(me, "number od nsw state allocated = %d\n", 626 ctrl_p->allocated); 627 _nscd_logit(me, "first nsw state on list = %p\n", 628 ctrl_p->first); 629 _nscd_logit(me, "number of waiter = %d\n", 630 ctrl_p->waiter); 631 } 632 633 if (ctrl_p->first != NULL) { 634 s->next = ctrl_p->first; 635 ctrl_p->first = s; 636 } else { 637 ctrl_p->first = s; 638 s->next = NULL; 639 } 640 ctrl_p->free++; 641 642 _NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG) 643 (me, "signaling waiter thread_only = %d..\n", thread_only); 644 645 if (thread_only && ctrl_p->free == ctrl_p->allocated) { 646 assert(ctrl_p->first != NULL); 647 base->used_by_thr = 0; 648 if (ctrl_p->waiter > 0) { 649 (void) cond_signal(&base->thr_cond); 650 } 651 } 652 653 if (!thread_only && ctrl_p->waiter > 0) { 654 655 _nscd_cond_signal((nscd_acc_data_t *)base); 656 } 657 658 _NSCD_LOG_IF(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG) { 659 _nscd_logit(me, "after the nsw state is returned: \n"); 660 _nscd_logit(me, "tid = %d\n", (tid == NULL) ? -1 : *tid); 661 _nscd_logit(me, "tid in base = %d\n", base->tid); 662 _nscd_logit(me, "number of free nsw_state = %d\n", 663 ctrl_p->free); 664 _nscd_logit(me, "number od nsw state allocated = %d\n", 665 ctrl_p->allocated); 666 _nscd_logit(me, "first nsw state on list = %p\n", 667 ctrl_p->first); 668 _nscd_logit(me, "tnumber of waiter = %d\n", 669 ctrl_p->waiter); 670 } 671 672 _NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG) 673 (me, "done putting back nsw state %p, thread_only = %d\n", 674 s, thread_only); 675 676 _nscd_mutex_unlock((nscd_acc_data_t *)base); 677 678 } 679 680 void 681 _nscd_put_nsw_state( 682 nscd_nsw_state_t *s) 683 { 684 _put_nsw_state_int(s, NULL); 685 } 686 687 void 688 _nscd_put_nsw_state_thread( 689 nscd_nsw_state_t *s) 690 { 691 thread_t tid = thr_self(); 692 _put_nsw_state_int(s, &tid); 693 } 694 695 nscd_rc_t 696 _nscd_init_nsw_state_base( 697 int dbi, 698 int compat_basei, 699 int lock) 700 { 701 int cfgdbi; 702 nscd_nsw_state_base_t *base = NULL; 703 char *me = "_nscd_init_nsw_state_base"; 704 705 if (lock) 706 (void) rw_rdlock(&nscd_nsw_state_base_lock); 707 708 base = (nscd_nsw_state_base_t *)_nscd_alloc( 709 NSCD_DATA_NSW_STATE_BASE, 710 sizeof (nscd_nsw_state_base_t), 711 _nscd_free_nsw_state_base, 712 NSCD_ALLOC_MUTEX | NSCD_ALLOC_COND); 713 714 if (base == NULL) { 715 _NSCD_LOG(NSCD_LOG_NSW_STATE | NSCD_LOG_CONFIG, 716 NSCD_LOG_LEVEL_ERROR) 717 (me, "not able to allocate a nsw state base\n"); 718 if (lock) 719 (void) rw_unlock(&nscd_nsw_state_base_lock); 720 return (NSCD_NO_MEMORY); 721 } 722 _NSCD_LOG(NSCD_LOG_NSW_STATE | NSCD_LOG_CONFIG, 723 NSCD_LOG_LEVEL_DEBUG) 724 (me, "nsw state base %p allocated\n", base); 725 726 /* 727 * initialize and activate the new nss_nsw_state base 728 */ 729 base->dbi = dbi; 730 if (compat_basei != -1) 731 cfgdbi = compat_basei; 732 else 733 cfgdbi = dbi; 734 735 base->nsw_state.max = NSCD_SW_CFG(cfgdbi).max_nsw_state_per_db; 736 base->nsw_state_thr.max = NSCD_SW_CFG(cfgdbi).max_nsw_state_per_thread; 737 738 nscd_nsw_state_base[dbi] = (nscd_nsw_state_base_t *)_nscd_set( 739 (nscd_acc_data_t *)nscd_nsw_state_base[dbi], 740 (nscd_acc_data_t *)base); 741 742 if (lock) 743 (void) rw_unlock(&nscd_nsw_state_base_lock); 744 745 return (NSCD_SUCCESS); 746 } 747 748 nscd_rc_t 749 _nscd_init_all_nsw_state_base() 750 { 751 int i; 752 nscd_rc_t rc; 753 char *me = "_nscd_init_all_nsw_state_base"; 754 755 (void) rw_rdlock(&nscd_nsw_state_base_lock); 756 757 for (i = 0; i < NSCD_NUM_DB; i++) { 758 759 rc = _nscd_init_nsw_state_base(i, -1, 0); 760 761 if (rc != NSCD_SUCCESS) { 762 _NSCD_LOG(NSCD_LOG_NSW_STATE | NSCD_LOG_CONFIG, 763 NSCD_LOG_LEVEL_ERROR) 764 (me, "not able to initialize a nsw db state " 765 "base (%d)\n", i); 766 767 (void) rw_unlock(&nscd_nsw_state_base_lock); 768 return (rc); 769 } 770 } 771 _NSCD_LOG(NSCD_LOG_NSW_STATE | NSCD_LOG_CONFIG, 772 NSCD_LOG_LEVEL_DEBUG) 773 (me, "all nsw state base initialized\n"); 774 775 (void) rw_unlock(&nscd_nsw_state_base_lock); 776 777 return (NSCD_SUCCESS); 778 } 779 780 nscd_rc_t 781 _nscd_alloc_nsw_state_base() 782 { 783 784 (void) rw_rdlock(&nscd_nsw_state_base_lock); 785 786 nscd_nsw_state_base = calloc(NSCD_NUM_DB, 787 sizeof (nscd_nsw_state_base_t *)); 788 if (nscd_nsw_state_base == NULL) { 789 (void) rw_unlock(&nscd_nsw_state_base_lock); 790 return (NSCD_NO_MEMORY); 791 } 792 793 (void) rw_rdlock(&nscd_nsw_state_base_lock); 794 795 return (NSCD_SUCCESS); 796 } 797