* sort crossdomain free buckets to domain correct buckets and cache * them. */
| 4280 | * them. |
| 4281 | */ |
| 4282 | static void |
| 4283 | zone_free_cross(uma_zone_t zone, uma_bucket_t bucket, void *udata) |
| 4284 | { |
| 4285 | struct uma_bucketlist emptybuckets, fullbuckets; |
| 4286 | uma_zone_domain_t zdom; |
| 4287 | uma_bucket_t b; |
| 4288 | smr_seq_t seq; |
| 4289 | void *item; |
| 4290 | int domain; |
| 4291 | |
| 4292 | CTR3(KTR_UMA, |
| 4293 | "uma_zfree: zone %s(%p) draining cross bucket %p", |
| 4294 | zone->uz_name, zone, bucket); |
| 4295 | |
| 4296 | /* |
| 4297 | * It is possible for buckets to arrive here out of order so we fetch |
| 4298 | * the current smr seq rather than accepting the bucket's. |
| 4299 | */ |
| 4300 | seq = SMR_SEQ_INVALID; |
| 4301 | if ((zone->uz_flags & UMA_ZONE_SMR) != 0) |
| 4302 | seq = smr_advance(zone->uz_smr); |
| 4303 | |
| 4304 | /* |
| 4305 | * To avoid having ndomain * ndomain buckets for sorting we have a |
| 4306 | * lock on the current crossfree bucket. A full matrix with |
| 4307 | * per-domain locking could be used if necessary. |
| 4308 | */ |
| 4309 | STAILQ_INIT(&emptybuckets); |
| 4310 | STAILQ_INIT(&fullbuckets); |
| 4311 | ZONE_CROSS_LOCK(zone); |
| 4312 | for (; bucket->ub_cnt > 0; bucket->ub_cnt--) { |
| 4313 | item = bucket->ub_bucket[bucket->ub_cnt - 1]; |
| 4314 | domain = item_domain(item); |
| 4315 | zdom = ZDOM_GET(zone, domain); |
| 4316 | if (zdom->uzd_cross == NULL) { |
| 4317 | if ((b = STAILQ_FIRST(&emptybuckets)) != NULL) { |
| 4318 | STAILQ_REMOVE_HEAD(&emptybuckets, ub_link); |
| 4319 | zdom->uzd_cross = b; |
| 4320 | } else { |
| 4321 | /* |
| 4322 | * Avoid allocating a bucket with the cross lock |
| 4323 | * held, since allocation can trigger a |
| 4324 | * cross-domain free and bucket zones may |
| 4325 | * allocate from each other. |
| 4326 | */ |
| 4327 | ZONE_CROSS_UNLOCK(zone); |
| 4328 | b = bucket_alloc(zone, udata, M_NOWAIT); |
| 4329 | if (b == NULL) |
| 4330 | goto out; |
| 4331 | ZONE_CROSS_LOCK(zone); |
| 4332 | if (zdom->uzd_cross != NULL) { |
| 4333 | STAILQ_INSERT_HEAD(&emptybuckets, b, |
| 4334 | ub_link); |
| 4335 | } else { |
| 4336 | zdom->uzd_cross = b; |
| 4337 | } |
| 4338 | } |
| 4339 | } |
no test coverage detected