* Lookup or create a domainset. The key is provided in ds_mask and * ds_policy. If the domainset does not yet exist the storage in * 'domain' is used to insert. Otherwise this storage is freed to the * domainset_zone and the existing domainset is returned. */
| 477 | * domainset_zone and the existing domainset is returned. |
| 478 | */ |
| 479 | static struct domainset * |
| 480 | _domainset_create(struct domainset *domain, struct domainlist *freelist) |
| 481 | { |
| 482 | struct domainset *ndomain; |
| 483 | int i, j; |
| 484 | |
| 485 | KASSERT(domain->ds_cnt <= vm_ndomains, |
| 486 | ("invalid domain count in domainset %p", domain)); |
| 487 | KASSERT(domain->ds_policy != DOMAINSET_POLICY_PREFER || |
| 488 | domain->ds_prefer < vm_ndomains, |
| 489 | ("invalid preferred domain in domains %p", domain)); |
| 490 | |
| 491 | mtx_lock_spin(&cpuset_lock); |
| 492 | LIST_FOREACH(ndomain, &cpuset_domains, ds_link) |
| 493 | if (domainset_equal(ndomain, domain)) |
| 494 | break; |
| 495 | /* |
| 496 | * If the domain does not yet exist we insert it and initialize |
| 497 | * various iteration helpers which are not part of the key. |
| 498 | */ |
| 499 | if (ndomain == NULL) { |
| 500 | LIST_INSERT_HEAD(&cpuset_domains, domain, ds_link); |
| 501 | domain->ds_cnt = DOMAINSET_COUNT(&domain->ds_mask); |
| 502 | for (i = 0, j = 0; i < DOMAINSET_FLS(&domain->ds_mask); i++) |
| 503 | if (DOMAINSET_ISSET(i, &domain->ds_mask)) |
| 504 | domain->ds_order[j++] = i; |
| 505 | } |
| 506 | mtx_unlock_spin(&cpuset_lock); |
| 507 | if (ndomain == NULL) |
| 508 | return (domain); |
| 509 | if (freelist != NULL) |
| 510 | LIST_INSERT_HEAD(freelist, domain, ds_link); |
| 511 | else |
| 512 | uma_zfree(domainset_zone, domain); |
| 513 | return (ndomain); |
| 514 | |
| 515 | } |
| 516 | |
| 517 | /* |
| 518 | * Are any of the domains in the mask empty? If so, silently |
no test coverage detected