This source file includes following definitions.
- pr_log
- pr_printlog
- pr_enter
- pr_leave
- pr_enter_check
- phtree_compare
- pr_find_pagehead
- pr_rmpage
- pool_init
- pool_setipl
- pool_destroy
- pool_alloc_item_header
- _pool_get
- pool_do_put
- _pool_put
- pool_put
- pool_prime
- pool_prime_page
- pool_catchup
- pool_update_curpage
- pool_setlowat
- pool_sethiwat
- pool_sethardlimit
- _pool_reclaim
- pool_printit
- pool_print_pagelist
- pool_print1
- db_show_all_pools
- pool_chk_page
- pool_chk
- pool_cache_init
- pool_cache_destroy
- pcg_get
- pcg_put
- pool_cache_get
- pool_cache_put
- pool_cache_destruct_object
- pool_cache_do_invalidate
- pool_cache_invalidate
- pool_cache_reclaim
- sysctl_dopool
- pool_allocator_alloc
- pool_allocator_free
- pool_page_alloc
- pool_page_free
- pool_page_alloc_oldnointr
- pool_page_free_oldnointr
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41 #include <sys/param.h>
42 #include <sys/systm.h>
43 #include <sys/proc.h>
44 #include <sys/errno.h>
45 #include <sys/kernel.h>
46 #include <sys/malloc.h>
47 #include <sys/lock.h>
48 #include <sys/pool.h>
49 #include <sys/syslog.h>
50 #include <sys/sysctl.h>
51
52 #include <uvm/uvm.h>
53
54
55
56
57 #ifdef LOCKDEBUG
58 #define simple_lock_freecheck(a, s) do { } while (0)
59 #define simple_lock_only_held(lkp, str) do { } while (0)
60 #endif
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76 TAILQ_HEAD(,pool) pool_head = TAILQ_HEAD_INITIALIZER(pool_head);
77
78
79 static struct pool phpool;
80
81
82 struct simplelock pool_head_slock;
83
84 struct pool_item_header {
85
86 LIST_ENTRY(pool_item_header)
87 ph_pagelist;
88 TAILQ_HEAD(,pool_item) ph_itemlist;
89 SPLAY_ENTRY(pool_item_header)
90 ph_node;
91 int ph_nmissing;
92 caddr_t ph_page;
93 };
94
95 struct pool_item {
96 #ifdef DIAGNOSTIC
97 int pi_magic;
98 #endif
99 #ifdef DEADBEEF1
100 #define PI_MAGIC DEADBEEF1
101 #else
102 #define PI_MAGIC 0xdeafbeef
103 #endif
104
105 TAILQ_ENTRY(pool_item) pi_list;
106 };
107
108 #define POOL_NEEDS_CATCHUP(pp) \
109 ((pp)->pr_nitems < (pp)->pr_minitems)
110
111
112
113
114
115 unsigned int pool_serial;
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144 static struct pool pcgpool;
145
146
147 #define PCG_NOBJECTS 16
148 struct pool_cache_group {
149 TAILQ_ENTRY(pool_cache_group)
150 pcg_list;
151 u_int pcg_avail;
152
153 void *pcg_objects[PCG_NOBJECTS];
154 };
155
156 void pool_cache_reclaim(struct pool_cache *);
157 void pool_cache_do_invalidate(struct pool_cache *, int,
158 void (*)(struct pool *, void *));
159
160 int pool_catchup(struct pool *);
161 void pool_prime_page(struct pool *, caddr_t, struct pool_item_header *);
162 void pool_update_curpage(struct pool *);
163 void pool_do_put(struct pool *, void *);
164 void pr_rmpage(struct pool *, struct pool_item_header *,
165 struct pool_pagelist *);
166 int pool_chk_page(struct pool *, const char *, struct pool_item_header *);
167
168 void *pool_allocator_alloc(struct pool *, int);
169 void pool_allocator_free(struct pool *, void *);
170
171 #ifdef DDB
172 void pool_print_pagelist(struct pool_pagelist *, int (*)(const char *, ...));
173 void pool_print1(struct pool *, const char *, int (*)(const char *, ...));
174 #endif
175
176
177
178
179
180 struct pool_log {
181 const char *pl_file;
182 long pl_line;
183 int pl_action;
184 #define PRLOG_GET 1
185 #define PRLOG_PUT 2
186 void *pl_addr;
187 };
188
189
190 #ifndef POOL_LOGSIZE
191 #define POOL_LOGSIZE 10
192 #endif
193
194 int pool_logsize = POOL_LOGSIZE;
195
196 #ifdef POOL_DIAGNOSTIC
197 static __inline void
198 pr_log(struct pool *pp, void *v, int action, const char *file, long line)
199 {
200 int n = pp->pr_curlogentry;
201 struct pool_log *pl;
202
203 if ((pp->pr_roflags & PR_LOGGING) == 0)
204 return;
205
206
207
208
209
210 pl = &pp->pr_log[n];
211 pl->pl_file = file;
212 pl->pl_line = line;
213 pl->pl_action = action;
214 pl->pl_addr = v;
215 if (++n >= pp->pr_logsize)
216 n = 0;
217 pp->pr_curlogentry = n;
218 }
219
220 static void
221 pr_printlog(struct pool *pp, struct pool_item *pi,
222 int (*pr)(const char *, ...))
223 {
224 int i = pp->pr_logsize;
225 int n = pp->pr_curlogentry;
226
227 if ((pp->pr_roflags & PR_LOGGING) == 0)
228 return;
229
230
231
232
233 while (i-- > 0) {
234 struct pool_log *pl = &pp->pr_log[n];
235 if (pl->pl_action != 0) {
236 if (pi == NULL || pi == pl->pl_addr) {
237 (*pr)("\tlog entry %d:\n", i);
238 (*pr)("\t\taction = %s, addr = %p\n",
239 pl->pl_action == PRLOG_GET ? "get" : "put",
240 pl->pl_addr);
241 (*pr)("\t\tfile: %s at line %lu\n",
242 pl->pl_file, pl->pl_line);
243 }
244 }
245 if (++n >= pp->pr_logsize)
246 n = 0;
247 }
248 }
249
250 static __inline void
251 pr_enter(struct pool *pp, const char *file, long line)
252 {
253
254 if (__predict_false(pp->pr_entered_file != NULL)) {
255 printf("pool %s: reentrancy at file %s line %ld\n",
256 pp->pr_wchan, file, line);
257 printf(" previous entry at file %s line %ld\n",
258 pp->pr_entered_file, pp->pr_entered_line);
259 panic("pr_enter");
260 }
261
262 pp->pr_entered_file = file;
263 pp->pr_entered_line = line;
264 }
265
266 static __inline void
267 pr_leave(struct pool *pp)
268 {
269
270 if (__predict_false(pp->pr_entered_file == NULL)) {
271 printf("pool %s not entered?\n", pp->pr_wchan);
272 panic("pr_leave");
273 }
274
275 pp->pr_entered_file = NULL;
276 pp->pr_entered_line = 0;
277 }
278
279 static __inline void
280 pr_enter_check(struct pool *pp, int (*pr)(const char *, ...))
281 {
282
283 if (pp->pr_entered_file != NULL)
284 (*pr)("\n\tcurrently entered from file %s line %ld\n",
285 pp->pr_entered_file, pp->pr_entered_line);
286 }
287 #else
288 #define pr_log(pp, v, action, file, line)
289 #define pr_printlog(pp, pi, pr)
290 #define pr_enter(pp, file, line)
291 #define pr_leave(pp)
292 #define pr_enter_check(pp, pr)
293 #endif
294
295 static __inline int
296 phtree_compare(struct pool_item_header *a, struct pool_item_header *b)
297 {
298 if (a->ph_page < b->ph_page)
299 return (-1);
300 else if (a->ph_page > b->ph_page)
301 return (1);
302 else
303 return (0);
304 }
305
306 SPLAY_PROTOTYPE(phtree, pool_item_header, ph_node, phtree_compare);
307 SPLAY_GENERATE(phtree, pool_item_header, ph_node, phtree_compare);
308
309
310
311
312 static __inline struct pool_item_header *
313 pr_find_pagehead(struct pool *pp, caddr_t page)
314 {
315 struct pool_item_header *ph, tmp;
316
317 if ((pp->pr_roflags & PR_PHINPAGE) != 0)
318 return ((struct pool_item_header *)(page + pp->pr_phoffset));
319
320 tmp.ph_page = page;
321 ph = SPLAY_FIND(phtree, &pp->pr_phtree, &tmp);
322 return ph;
323 }
324
325
326
327
328 void
329 pr_rmpage(struct pool *pp, struct pool_item_header *ph,
330 struct pool_pagelist *pq)
331 {
332 int s;
333
334
335
336
337 if (ph->ph_nmissing == 0) {
338 #ifdef DIAGNOSTIC
339 if (pp->pr_nidle == 0)
340 panic("pr_rmpage: nidle inconsistent");
341 if (pp->pr_nitems < pp->pr_itemsperpage)
342 panic("pr_rmpage: nitems inconsistent");
343 #endif
344 pp->pr_nidle--;
345 }
346
347 pp->pr_nitems -= pp->pr_itemsperpage;
348
349
350
351
352 LIST_REMOVE(ph, ph_pagelist);
353 if (pq) {
354 LIST_INSERT_HEAD(pq, ph, ph_pagelist);
355 } else {
356 pool_allocator_free(pp, ph->ph_page);
357 if ((pp->pr_roflags & PR_PHINPAGE) == 0) {
358 SPLAY_REMOVE(phtree, &pp->pr_phtree, ph);
359 s = splhigh();
360 pool_put(&phpool, ph);
361 splx(s);
362 }
363 }
364 pp->pr_npages--;
365 pp->pr_npagefree++;
366
367 pool_update_curpage(pp);
368 }
369
370
371
372
373
374
375
376 void
377 pool_init(struct pool *pp, size_t size, u_int align, u_int ioff, int flags,
378 const char *wchan, struct pool_allocator *palloc)
379 {
380 int off, slack;
381
382 #ifdef POOL_DIAGNOSTIC
383
384
385
386 if (pool_logsize != 0)
387 flags |= PR_LOGGING;
388 #endif
389
390 #ifdef MALLOC_DEBUG
391 if ((flags & PR_DEBUG) && (ioff != 0 || align != 0))
392 flags &= ~PR_DEBUG;
393 #endif
394
395
396
397 if (palloc == NULL)
398 palloc = &pool_allocator_nointr;
399 if ((palloc->pa_flags & PA_INITIALIZED) == 0) {
400 if (palloc->pa_pagesz == 0)
401 palloc->pa_pagesz = PAGE_SIZE;
402
403 TAILQ_INIT(&palloc->pa_list);
404
405 simple_lock_init(&palloc->pa_slock);
406 palloc->pa_pagemask = ~(palloc->pa_pagesz - 1);
407 palloc->pa_pageshift = ffs(palloc->pa_pagesz) - 1;
408 palloc->pa_flags |= PA_INITIALIZED;
409 }
410
411 if (align == 0)
412 align = ALIGN(1);
413
414 if (size < sizeof(struct pool_item))
415 size = sizeof(struct pool_item);
416
417 size = roundup(size, align);
418 #ifdef DIAGNOSTIC
419 if (size > palloc->pa_pagesz)
420 panic("pool_init: pool item size (%lu) too large",
421 (u_long)size);
422 #endif
423
424
425
426
427 LIST_INIT(&pp->pr_emptypages);
428 LIST_INIT(&pp->pr_fullpages);
429 LIST_INIT(&pp->pr_partpages);
430 TAILQ_INIT(&pp->pr_cachelist);
431 pp->pr_curpage = NULL;
432 pp->pr_npages = 0;
433 pp->pr_minitems = 0;
434 pp->pr_minpages = 0;
435 pp->pr_maxpages = 8;
436 pp->pr_roflags = flags;
437 pp->pr_flags = 0;
438 pp->pr_size = size;
439 pp->pr_align = align;
440 pp->pr_wchan = wchan;
441 pp->pr_alloc = palloc;
442 pp->pr_nitems = 0;
443 pp->pr_nout = 0;
444 pp->pr_hardlimit = UINT_MAX;
445 pp->pr_hardlimit_warning = NULL;
446 pp->pr_hardlimit_ratecap.tv_sec = 0;
447 pp->pr_hardlimit_ratecap.tv_usec = 0;
448 pp->pr_hardlimit_warning_last.tv_sec = 0;
449 pp->pr_hardlimit_warning_last.tv_usec = 0;
450 pp->pr_serial = ++pool_serial;
451 if (pool_serial == 0)
452 panic("pool_init: too much uptime");
453
454
455
456
457
458
459
460
461 if (pp->pr_size < palloc->pa_pagesz/16) {
462
463 pp->pr_roflags |= PR_PHINPAGE;
464 pp->pr_phoffset = off = palloc->pa_pagesz -
465 ALIGN(sizeof(struct pool_item_header));
466 } else {
467
468 pp->pr_phoffset = 0;
469 off = palloc->pa_pagesz;
470 SPLAY_INIT(&pp->pr_phtree);
471 }
472
473
474
475
476
477
478
479
480 pp->pr_itemoffset = ioff = ioff % align;
481 pp->pr_itemsperpage = (off - ((align - ioff) % align)) / pp->pr_size;
482 KASSERT(pp->pr_itemsperpage != 0);
483
484
485
486
487
488 slack = off - pp->pr_itemsperpage * pp->pr_size;
489 pp->pr_maxcolor = (slack / align) * align;
490 pp->pr_curcolor = 0;
491
492 pp->pr_nget = 0;
493 pp->pr_nfail = 0;
494 pp->pr_nput = 0;
495 pp->pr_npagealloc = 0;
496 pp->pr_npagefree = 0;
497 pp->pr_hiwat = 0;
498 pp->pr_nidle = 0;
499
500 #ifdef POOL_DIAGNOSTIC
501 if (flags & PR_LOGGING) {
502 if (kmem_map == NULL ||
503 (pp->pr_log = malloc(pool_logsize * sizeof(struct pool_log),
504 M_TEMP, M_NOWAIT)) == NULL)
505 pp->pr_roflags &= ~PR_LOGGING;
506 pp->pr_curlogentry = 0;
507 pp->pr_logsize = pool_logsize;
508 }
509 #endif
510
511 pp->pr_entered_file = NULL;
512 pp->pr_entered_line = 0;
513
514 simple_lock_init(&pp->pr_slock);
515
516 pp->pr_ipl = -1;
517
518
519
520
521
522
523 if (phpool.pr_size == 0) {
524 pool_init(&phpool, sizeof(struct pool_item_header), 0, 0,
525 0, "phpool", NULL);
526 pool_init(&pcgpool, sizeof(struct pool_cache_group), 0, 0,
527 0, "pcgpool", NULL);
528 }
529
530 simple_lock_init(&pool_head_slock);
531
532
533 simple_lock(&pool_head_slock);
534 TAILQ_INSERT_TAIL(&pool_head, pp, pr_poollist);
535 simple_unlock(&pool_head_slock);
536
537
538 simple_lock(&palloc->pa_slock);
539 TAILQ_INSERT_TAIL(&palloc->pa_list, pp, pr_alloc_list);
540 simple_unlock(&palloc->pa_slock);
541 }
542
543 #ifdef DIAGNOSTIC
544 void
545 pool_setipl(struct pool *pp, int ipl)
546 {
547 pp->pr_ipl = ipl;
548 }
549 #endif
550
551
552
553
554 void
555 pool_destroy(struct pool *pp)
556 {
557 struct pool_item_header *ph;
558 struct pool_cache *pc;
559
560
561 simple_lock(&pp->pr_alloc->pa_slock);
562 TAILQ_REMOVE(&pp->pr_alloc->pa_list, pp, pr_alloc_list);
563 simple_unlock(&pp->pr_alloc->pa_slock);
564
565
566 while ((pc = TAILQ_FIRST(&pp->pr_cachelist)) != NULL)
567 pool_cache_destroy(pc);
568
569 #ifdef DIAGNOSTIC
570 if (pp->pr_nout != 0) {
571 pr_printlog(pp, NULL, printf);
572 panic("pool_destroy: pool busy: still out: %u",
573 pp->pr_nout);
574 }
575 #endif
576
577
578 while ((ph = LIST_FIRST(&pp->pr_emptypages)) != NULL)
579 pr_rmpage(pp, ph, NULL);
580 KASSERT(LIST_EMPTY(&pp->pr_fullpages));
581 KASSERT(LIST_EMPTY(&pp->pr_partpages));
582
583
584 simple_lock(&pool_head_slock);
585 TAILQ_REMOVE(&pool_head, pp, pr_poollist);
586 simple_unlock(&pool_head_slock);
587
588 #ifdef POOL_DIAGNOSTIC
589 if ((pp->pr_roflags & PR_LOGGING) != 0)
590 free(pp->pr_log, M_TEMP);
591 #endif
592 }
593
594 static struct pool_item_header *
595 pool_alloc_item_header(struct pool *pp, caddr_t storage, int flags)
596 {
597 struct pool_item_header *ph;
598 int s;
599
600 LOCK_ASSERT(simple_lock_held(&pp->pr_slock) == 0);
601
602 if ((pp->pr_roflags & PR_PHINPAGE) != 0)
603 ph = (struct pool_item_header *) (storage + pp->pr_phoffset);
604 else {
605 s = splhigh();
606 ph = pool_get(&phpool, flags);
607 splx(s);
608 }
609
610 return (ph);
611 }
612
613
614
615
616 void *
617 #ifdef POOL_DIAGNOSTIC
618 _pool_get(struct pool *pp, int flags, const char *file, long line)
619 #else
620 pool_get(struct pool *pp, int flags)
621 #endif
622 {
623 struct pool_item *pi;
624 struct pool_item_header *ph;
625 void *v;
626
627 #ifdef DIAGNOSTIC
628 if ((flags & PR_WAITOK) != 0)
629 splassert(IPL_NONE);
630 if (pp->pr_ipl != -1)
631 splassert(pp->pr_ipl);
632 if (__predict_false(curproc == NULL &&
633 (flags & PR_WAITOK) != 0))
634 panic("pool_get: %s:must have NOWAIT", pp->pr_wchan);
635
636 #ifdef LOCKDEBUG
637 if (flags & PR_WAITOK)
638 simple_lock_only_held(NULL, "pool_get(PR_WAITOK)");
639 #endif
640 #endif
641
642 #ifdef MALLOC_DEBUG
643 if (pp->pr_roflags & PR_DEBUG) {
644 void *addr;
645
646 addr = NULL;
647 debug_malloc(pp->pr_size, M_DEBUG,
648 (flags & PR_WAITOK) ? M_WAITOK : M_NOWAIT, &addr);
649 return (addr);
650 }
651 #endif
652
653 simple_lock(&pp->pr_slock);
654 pr_enter(pp, file, line);
655
656 startover:
657
658
659
660
661
662 #ifdef DIAGNOSTIC
663 if (__predict_false(pp->pr_nout > pp->pr_hardlimit)) {
664 pr_leave(pp);
665 simple_unlock(&pp->pr_slock);
666 panic("pool_get: %s: crossed hard limit", pp->pr_wchan);
667 }
668 #endif
669 if (__predict_false(pp->pr_nout == pp->pr_hardlimit)) {
670 if ((flags & PR_WAITOK) && !(flags & PR_LIMITFAIL)) {
671
672
673
674
675 pp->pr_flags |= PR_WANTED;
676 pr_leave(pp);
677 ltsleep(pp, PSWP, pp->pr_wchan, 0, &pp->pr_slock);
678 pr_enter(pp, file, line);
679 goto startover;
680 }
681
682
683
684
685 if (pp->pr_hardlimit_warning != NULL &&
686 ratecheck(&pp->pr_hardlimit_warning_last,
687 &pp->pr_hardlimit_ratecap))
688 log(LOG_ERR, "%s\n", pp->pr_hardlimit_warning);
689
690 pp->pr_nfail++;
691
692 pr_leave(pp);
693 simple_unlock(&pp->pr_slock);
694 return (NULL);
695 }
696
697
698
699
700
701
702
703 if ((ph = pp->pr_curpage) == NULL) {
704 #ifdef DIAGNOSTIC
705 if (pp->pr_nitems != 0) {
706 simple_unlock(&pp->pr_slock);
707 printf("pool_get: %s: curpage NULL, nitems %u\n",
708 pp->pr_wchan, pp->pr_nitems);
709 panic("pool_get: nitems inconsistent");
710 }
711 #endif
712
713
714
715
716
717
718 pr_leave(pp);
719 simple_unlock(&pp->pr_slock);
720 v = pool_allocator_alloc(pp, flags);
721 if (__predict_true(v != NULL))
722 ph = pool_alloc_item_header(pp, v, flags);
723 simple_lock(&pp->pr_slock);
724 pr_enter(pp, file, line);
725
726 if (__predict_false(v == NULL || ph == NULL)) {
727 if (v != NULL)
728 pool_allocator_free(pp, v);
729
730
731
732
733
734
735
736 if (pp->pr_curpage != NULL)
737 goto startover;
738
739 if ((flags & PR_WAITOK) == 0) {
740 pp->pr_nfail++;
741 pr_leave(pp);
742 simple_unlock(&pp->pr_slock);
743 return (NULL);
744 }
745
746
747
748
749
750
751
752 pp->pr_flags |= PR_WANTED;
753
754 pr_leave(pp);
755 ltsleep(pp, PSWP, pp->pr_wchan, 0, &pp->pr_slock);
756 pr_enter(pp, file, line);
757 goto startover;
758 }
759
760
761 pool_prime_page(pp, v, ph);
762 pp->pr_npagealloc++;
763
764
765 goto startover;
766 }
767 if (__predict_false((v = pi = TAILQ_FIRST(&ph->ph_itemlist)) == NULL)) {
768 pr_leave(pp);
769 simple_unlock(&pp->pr_slock);
770 panic("pool_get: %s: page empty", pp->pr_wchan);
771 }
772 #ifdef DIAGNOSTIC
773 if (__predict_false(pp->pr_nitems == 0)) {
774 pr_leave(pp);
775 simple_unlock(&pp->pr_slock);
776 printf("pool_get: %s: items on itemlist, nitems %u\n",
777 pp->pr_wchan, pp->pr_nitems);
778 panic("pool_get: nitems inconsistent");
779 }
780 #endif
781
782 #ifdef POOL_DIAGNOSTIC
783 pr_log(pp, v, PRLOG_GET, file, line);
784 #endif
785
786 #ifdef DIAGNOSTIC
787 if (__predict_false(pi->pi_magic != PI_MAGIC)) {
788 pr_printlog(pp, pi, printf);
789 panic("pool_get(%s): free list modified: magic=%x; page %p;"
790 " item addr %p",
791 pp->pr_wchan, pi->pi_magic, ph->ph_page, pi);
792 }
793 #endif
794
795
796
797
798 TAILQ_REMOVE(&ph->ph_itemlist, pi, pi_list);
799 pp->pr_nitems--;
800 pp->pr_nout++;
801 if (ph->ph_nmissing == 0) {
802 #ifdef DIAGNOSTIC
803 if (__predict_false(pp->pr_nidle == 0))
804 panic("pool_get: nidle inconsistent");
805 #endif
806 pp->pr_nidle--;
807
808
809
810
811
812 LIST_REMOVE(ph, ph_pagelist);
813 LIST_INSERT_HEAD(&pp->pr_partpages, ph, ph_pagelist);
814 }
815 ph->ph_nmissing++;
816 if (TAILQ_EMPTY(&ph->ph_itemlist)) {
817 #ifdef DIAGNOSTIC
818 if (__predict_false(ph->ph_nmissing != pp->pr_itemsperpage)) {
819 pr_leave(pp);
820 simple_unlock(&pp->pr_slock);
821 panic("pool_get: %s: nmissing inconsistent",
822 pp->pr_wchan);
823 }
824 #endif
825
826
827
828
829 LIST_REMOVE(ph, ph_pagelist);
830 LIST_INSERT_HEAD(&pp->pr_fullpages, ph, ph_pagelist);
831 pool_update_curpage(pp);
832 }
833
834 pp->pr_nget++;
835
836
837
838
839
840 if (POOL_NEEDS_CATCHUP(pp) && pool_catchup(pp) != 0) {
841
842
843
844
845
846 }
847
848 pr_leave(pp);
849 simple_unlock(&pp->pr_slock);
850 return (v);
851 }
852
853
854
855
856 void
857 pool_do_put(struct pool *pp, void *v)
858 {
859 struct pool_item *pi = v;
860 struct pool_item_header *ph;
861 caddr_t page;
862
863 #ifdef MALLOC_DEBUG
864 if (pp->pr_roflags & PR_DEBUG) {
865 debug_free(v, M_DEBUG);
866 return;
867 }
868 #endif
869
870 LOCK_ASSERT(simple_lock_held(&pp->pr_slock));
871
872 page = (caddr_t)((vaddr_t)v & pp->pr_alloc->pa_pagemask);
873
874 #ifdef DIAGNOSTIC
875 if (pp->pr_ipl != -1)
876 splassert(pp->pr_ipl);
877
878 if (__predict_false(pp->pr_nout == 0)) {
879 printf("pool %s: putting with none out\n",
880 pp->pr_wchan);
881 panic("pool_put");
882 }
883 #endif
884
885 if (__predict_false((ph = pr_find_pagehead(pp, page)) == NULL)) {
886 pr_printlog(pp, NULL, printf);
887 panic("pool_put: %s: page header missing", pp->pr_wchan);
888 }
889
890 #ifdef LOCKDEBUG
891
892
893
894 simple_lock_freecheck((caddr_t)pi, ((caddr_t)pi) + pp->pr_size);
895 #endif
896
897
898
899
900 #ifdef DIAGNOSTIC
901 pi->pi_magic = PI_MAGIC;
902 #endif
903 #ifdef DEBUG
904 {
905 int i, *ip = v;
906
907 for (i = 0; i < pp->pr_size / sizeof(int); i++) {
908 *ip++ = PI_MAGIC;
909 }
910 }
911 #endif
912
913 TAILQ_INSERT_HEAD(&ph->ph_itemlist, pi, pi_list);
914 ph->ph_nmissing--;
915 pp->pr_nput++;
916 pp->pr_nitems++;
917 pp->pr_nout--;
918
919
920 if (pp->pr_curpage == NULL)
921 pp->pr_curpage = ph;
922
923 if (pp->pr_flags & PR_WANTED) {
924 pp->pr_flags &= ~PR_WANTED;
925 if (ph->ph_nmissing == 0)
926 pp->pr_nidle++;
927 wakeup(pp);
928 return;
929 }
930
931
932
933
934
935
936
937
938
939
940
941
942 if (ph->ph_nmissing == 0) {
943 pp->pr_nidle++;
944 if (pp->pr_nidle > pp->pr_maxpages ||
945 (pp->pr_alloc->pa_flags & PA_WANT) != 0) {
946 pr_rmpage(pp, ph, NULL);
947 } else {
948 LIST_REMOVE(ph, ph_pagelist);
949 LIST_INSERT_HEAD(&pp->pr_emptypages, ph, ph_pagelist);
950 }
951 pool_update_curpage(pp);
952 }
953
954
955
956
957
958
959
960 else if (ph->ph_nmissing == (pp->pr_itemsperpage - 1)) {
961 LIST_REMOVE(ph, ph_pagelist);
962 LIST_INSERT_HEAD(&pp->pr_partpages, ph, ph_pagelist);
963 pp->pr_curpage = ph;
964 }
965 }
966
967
968
969
970 #ifdef POOL_DIAGNOSTIC
971 void
972 _pool_put(struct pool *pp, void *v, const char *file, long line)
973 {
974
975 simple_lock(&pp->pr_slock);
976 pr_enter(pp, file, line);
977
978 pr_log(pp, v, PRLOG_PUT, file, line);
979
980 pool_do_put(pp, v);
981
982 pr_leave(pp);
983 simple_unlock(&pp->pr_slock);
984 }
985 #undef pool_put
986 #endif
987
988 void
989 pool_put(struct pool *pp, void *v)
990 {
991
992 simple_lock(&pp->pr_slock);
993
994 pool_do_put(pp, v);
995
996 simple_unlock(&pp->pr_slock);
997 }
998
999 #ifdef POOL_DIAGNOSTIC
1000 #define pool_put(h, v) _pool_put((h), (v), __FILE__, __LINE__)
1001 #endif
1002
1003
1004
1005
1006 int
1007 pool_prime(struct pool *pp, int n)
1008 {
1009 struct pool_item_header *ph;
1010 caddr_t cp;
1011 int newpages;
1012
1013 simple_lock(&pp->pr_slock);
1014
1015 newpages = roundup(n, pp->pr_itemsperpage) / pp->pr_itemsperpage;
1016
1017 while (newpages-- > 0) {
1018 simple_unlock(&pp->pr_slock);
1019 cp = pool_allocator_alloc(pp, PR_NOWAIT);
1020 if (__predict_true(cp != NULL))
1021 ph = pool_alloc_item_header(pp, cp, PR_NOWAIT);
1022 simple_lock(&pp->pr_slock);
1023
1024 if (__predict_false(cp == NULL || ph == NULL)) {
1025 if (cp != NULL)
1026 pool_allocator_free(pp, cp);
1027 break;
1028 }
1029
1030 pool_prime_page(pp, cp, ph);
1031 pp->pr_npagealloc++;
1032 pp->pr_minpages++;
1033 }
1034
1035 if (pp->pr_minpages >= pp->pr_maxpages)
1036 pp->pr_maxpages = pp->pr_minpages + 1;
1037
1038 simple_unlock(&pp->pr_slock);
1039 return (0);
1040 }
1041
1042
1043
1044
1045
1046
1047 void
1048 pool_prime_page(struct pool *pp, caddr_t storage, struct pool_item_header *ph)
1049 {
1050 struct pool_item *pi;
1051 caddr_t cp = storage;
1052 unsigned int align = pp->pr_align;
1053 unsigned int ioff = pp->pr_itemoffset;
1054 int n;
1055
1056 #ifdef DIAGNOSTIC
1057 if (((u_long)cp & (pp->pr_alloc->pa_pagesz - 1)) != 0)
1058 panic("pool_prime_page: %s: unaligned page", pp->pr_wchan);
1059 #endif
1060
1061
1062
1063
1064 LIST_INSERT_HEAD(&pp->pr_emptypages, ph, ph_pagelist);
1065 TAILQ_INIT(&ph->ph_itemlist);
1066 ph->ph_page = storage;
1067 ph->ph_nmissing = 0;
1068 if ((pp->pr_roflags & PR_PHINPAGE) == 0)
1069 SPLAY_INSERT(phtree, &pp->pr_phtree, ph);
1070
1071 pp->pr_nidle++;
1072
1073
1074
1075
1076 cp = (caddr_t)(cp + pp->pr_curcolor);
1077 if ((pp->pr_curcolor += align) > pp->pr_maxcolor)
1078 pp->pr_curcolor = 0;
1079
1080
1081
1082
1083 if (ioff != 0)
1084 cp = (caddr_t)(cp + (align - ioff));
1085
1086
1087
1088
1089 n = pp->pr_itemsperpage;
1090 pp->pr_nitems += n;
1091
1092 while (n--) {
1093 pi = (struct pool_item *)cp;
1094
1095 KASSERT(((((vaddr_t)pi) + ioff) & (align - 1)) == 0);
1096
1097
1098 TAILQ_INSERT_TAIL(&ph->ph_itemlist, pi, pi_list);
1099 #ifdef DIAGNOSTIC
1100 pi->pi_magic = PI_MAGIC;
1101 #endif
1102 cp = (caddr_t)(cp + pp->pr_size);
1103 }
1104
1105
1106
1107
1108 if (pp->pr_curpage == NULL)
1109 pp->pr_curpage = ph;
1110
1111 if (++pp->pr_npages > pp->pr_hiwat)
1112 pp->pr_hiwat = pp->pr_npages;
1113 }
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124 int
1125 pool_catchup(struct pool *pp)
1126 {
1127 struct pool_item_header *ph;
1128 caddr_t cp;
1129 int error = 0;
1130
1131 while (POOL_NEEDS_CATCHUP(pp)) {
1132
1133
1134
1135
1136
1137
1138 simple_unlock(&pp->pr_slock);
1139 cp = pool_allocator_alloc(pp, PR_NOWAIT);
1140 if (__predict_true(cp != NULL))
1141 ph = pool_alloc_item_header(pp, cp, PR_NOWAIT);
1142 simple_lock(&pp->pr_slock);
1143 if (__predict_false(cp == NULL || ph == NULL)) {
1144 if (cp != NULL)
1145 pool_allocator_free(pp, cp);
1146 error = ENOMEM;
1147 break;
1148 }
1149 pool_prime_page(pp, cp, ph);
1150 pp->pr_npagealloc++;
1151 }
1152
1153 return (error);
1154 }
1155
1156 void
1157 pool_update_curpage(struct pool *pp)
1158 {
1159
1160 pp->pr_curpage = LIST_FIRST(&pp->pr_partpages);
1161 if (pp->pr_curpage == NULL) {
1162 pp->pr_curpage = LIST_FIRST(&pp->pr_emptypages);
1163 }
1164 }
1165
1166 void
1167 pool_setlowat(struct pool *pp, int n)
1168 {
1169
1170 simple_lock(&pp->pr_slock);
1171
1172 pp->pr_minitems = n;
1173 pp->pr_minpages = (n == 0)
1174 ? 0
1175 : roundup(n, pp->pr_itemsperpage) / pp->pr_itemsperpage;
1176
1177
1178 if (POOL_NEEDS_CATCHUP(pp) && pool_catchup(pp) != 0) {
1179
1180
1181
1182
1183
1184 }
1185
1186 simple_unlock(&pp->pr_slock);
1187 }
1188
1189 void
1190 pool_sethiwat(struct pool *pp, int n)
1191 {
1192
1193 simple_lock(&pp->pr_slock);
1194
1195 pp->pr_maxpages = (n == 0)
1196 ? 0
1197 : roundup(n, pp->pr_itemsperpage) / pp->pr_itemsperpage;
1198
1199 simple_unlock(&pp->pr_slock);
1200 }
1201
1202 int
1203 pool_sethardlimit(struct pool *pp, unsigned n, const char *warnmess, int ratecap)
1204 {
1205 int error = 0;
1206
1207 simple_lock(&pp->pr_slock);
1208
1209 if (n < pp->pr_nout) {
1210 error = EINVAL;
1211 goto done;
1212 }
1213
1214 pp->pr_hardlimit = n;
1215 pp->pr_hardlimit_warning = warnmess;
1216 pp->pr_hardlimit_ratecap.tv_sec = ratecap;
1217 pp->pr_hardlimit_warning_last.tv_sec = 0;
1218 pp->pr_hardlimit_warning_last.tv_usec = 0;
1219
1220
1221
1222
1223
1224 pp->pr_maxpages = (n == 0 || n == UINT_MAX)
1225 ? n
1226 : roundup(n, pp->pr_itemsperpage) / pp->pr_itemsperpage;
1227
1228 done:
1229 simple_unlock(&pp->pr_slock);
1230
1231 return (error);
1232 }
1233
1234
1235
1236
1237
1238
1239 int
1240 #ifdef POOL_DIAGNOSTIC
1241 _pool_reclaim(struct pool *pp, const char *file, long line)
1242 #else
1243 pool_reclaim(struct pool *pp)
1244 #endif
1245 {
1246 struct pool_item_header *ph, *phnext;
1247 struct pool_cache *pc;
1248 struct pool_pagelist pq;
1249 int s;
1250
1251 if (simple_lock_try(&pp->pr_slock) == 0)
1252 return (0);
1253 pr_enter(pp, file, line);
1254
1255 LIST_INIT(&pq);
1256
1257
1258
1259
1260 TAILQ_FOREACH(pc, &pp->pr_cachelist, pc_poollist)
1261 pool_cache_reclaim(pc);
1262
1263 for (ph = LIST_FIRST(&pp->pr_emptypages); ph != NULL; ph = phnext) {
1264 phnext = LIST_NEXT(ph, ph_pagelist);
1265
1266
1267 if (pp->pr_npages <= pp->pr_minpages)
1268 break;
1269
1270 KASSERT(ph->ph_nmissing == 0);
1271
1272
1273
1274
1275
1276 if ((pp->pr_nitems - pp->pr_itemsperpage) <
1277 pp->pr_minitems)
1278 break;
1279
1280 pr_rmpage(pp, ph, &pq);
1281 }
1282
1283 pr_leave(pp);
1284 simple_unlock(&pp->pr_slock);
1285 if (LIST_EMPTY(&pq))
1286 return (0);
1287 while ((ph = LIST_FIRST(&pq)) != NULL) {
1288 LIST_REMOVE(ph, ph_pagelist);
1289 pool_allocator_free(pp, ph->ph_page);
1290 if (pp->pr_roflags & PR_PHINPAGE) {
1291 continue;
1292 }
1293 SPLAY_REMOVE(phtree, &pp->pr_phtree, ph);
1294 s = splhigh();
1295 pool_put(&phpool, ph);
1296 splx(s);
1297 }
1298
1299 return (1);
1300 }
1301
1302 #ifdef DDB
1303 #include <machine/db_machdep.h>
1304 #include <ddb/db_interface.h>
1305 #include <ddb/db_output.h>
1306
1307
1308
1309
1310 void
1311 pool_printit(struct pool *pp, const char *modif, int (*pr)(const char *, ...))
1312 {
1313 int s;
1314
1315 s = splvm();
1316 if (simple_lock_try(&pp->pr_slock) == 0) {
1317 pr("pool %s is locked; try again later\n",
1318 pp->pr_wchan);
1319 splx(s);
1320 return;
1321 }
1322 pool_print1(pp, modif, pr);
1323 simple_unlock(&pp->pr_slock);
1324 splx(s);
1325 }
1326
1327 void
1328 pool_print_pagelist(struct pool_pagelist *pl, int (*pr)(const char *, ...))
1329 {
1330 struct pool_item_header *ph;
1331 #ifdef DIAGNOSTIC
1332 struct pool_item *pi;
1333 #endif
1334
1335 LIST_FOREACH(ph, pl, ph_pagelist) {
1336 (*pr)("\t\tpage %p, nmissing %d\n",
1337 ph->ph_page, ph->ph_nmissing);
1338 #ifdef DIAGNOSTIC
1339 TAILQ_FOREACH(pi, &ph->ph_itemlist, pi_list) {
1340 if (pi->pi_magic != PI_MAGIC) {
1341 (*pr)("\t\t\titem %p, magic 0x%x\n",
1342 pi, pi->pi_magic);
1343 }
1344 }
1345 #endif
1346 }
1347 }
1348
1349 void
1350 pool_print1(struct pool *pp, const char *modif, int (*pr)(const char *, ...))
1351 {
1352 struct pool_item_header *ph;
1353 struct pool_cache *pc;
1354 struct pool_cache_group *pcg;
1355 int i, print_log = 0, print_pagelist = 0, print_cache = 0;
1356 char c;
1357
1358 while ((c = *modif++) != '\0') {
1359 if (c == 'l')
1360 print_log = 1;
1361 if (c == 'p')
1362 print_pagelist = 1;
1363 if (c == 'c')
1364 print_cache = 1;
1365 modif++;
1366 }
1367
1368 (*pr)("POOL %s: size %u, align %u, ioff %u, roflags 0x%08x\n",
1369 pp->pr_wchan, pp->pr_size, pp->pr_align, pp->pr_itemoffset,
1370 pp->pr_roflags);
1371 (*pr)("\talloc %p\n", pp->pr_alloc);
1372 (*pr)("\tminitems %u, minpages %u, maxpages %u, npages %u\n",
1373 pp->pr_minitems, pp->pr_minpages, pp->pr_maxpages, pp->pr_npages);
1374 (*pr)("\titemsperpage %u, nitems %u, nout %u, hardlimit %u\n",
1375 pp->pr_itemsperpage, pp->pr_nitems, pp->pr_nout, pp->pr_hardlimit);
1376
1377 (*pr)("\n\tnget %lu, nfail %lu, nput %lu\n",
1378 pp->pr_nget, pp->pr_nfail, pp->pr_nput);
1379 (*pr)("\tnpagealloc %lu, npagefree %lu, hiwat %u, nidle %lu\n",
1380 pp->pr_npagealloc, pp->pr_npagefree, pp->pr_hiwat, pp->pr_nidle);
1381
1382 if (print_pagelist == 0)
1383 goto skip_pagelist;
1384
1385 if ((ph = LIST_FIRST(&pp->pr_emptypages)) != NULL)
1386 (*pr)("\n\tempty page list:\n");
1387 pool_print_pagelist(&pp->pr_emptypages, pr);
1388 if ((ph = LIST_FIRST(&pp->pr_fullpages)) != NULL)
1389 (*pr)("\n\tfull page list:\n");
1390 pool_print_pagelist(&pp->pr_fullpages, pr);
1391 if ((ph = LIST_FIRST(&pp->pr_partpages)) != NULL)
1392 (*pr)("\n\tpartial-page list:\n");
1393 pool_print_pagelist(&pp->pr_partpages, pr);
1394
1395 if (pp->pr_curpage == NULL)
1396 (*pr)("\tno current page\n");
1397 else
1398 (*pr)("\tcurpage %p\n", pp->pr_curpage->ph_page);
1399
1400 skip_pagelist:
1401 if (print_log == 0)
1402 goto skip_log;
1403
1404 (*pr)("\n");
1405 if ((pp->pr_roflags & PR_LOGGING) == 0)
1406 (*pr)("\tno log\n");
1407 else
1408 pr_printlog(pp, NULL, pr);
1409
1410 skip_log:
1411 if (print_cache == 0)
1412 goto skip_cache;
1413
1414 TAILQ_FOREACH(pc, &pp->pr_cachelist, pc_poollist) {
1415 (*pr)("\tcache %p: allocfrom %p freeto %p\n", pc,
1416 pc->pc_allocfrom, pc->pc_freeto);
1417 (*pr)("\t hits %lu misses %lu ngroups %lu nitems %lu\n",
1418 pc->pc_hits, pc->pc_misses, pc->pc_ngroups, pc->pc_nitems);
1419 TAILQ_FOREACH(pcg, &pc->pc_grouplist, pcg_list) {
1420 (*pr)("\t\tgroup %p: avail %d\n", pcg, pcg->pcg_avail);
1421 for (i = 0; i < PCG_NOBJECTS; i++)
1422 (*pr)("\t\t\t%p\n", pcg->pcg_objects[i]);
1423 }
1424 }
1425
1426 skip_cache:
1427 pr_enter_check(pp, pr);
1428 }
1429
1430 void
1431 db_show_all_pools(db_expr_t expr, int haddr, db_expr_t count, char *modif)
1432 {
1433 struct pool *pp;
1434 char maxp[16];
1435 int ovflw;
1436 char mode;
1437
1438 mode = modif[0];
1439 if (mode != '\0' && mode != 'a') {
1440 db_printf("usage: show all pools [/a]\n");
1441 return;
1442 }
1443
1444 if (mode == '\0')
1445 db_printf("%-10s%4s%9s%5s%9s%6s%6s%6s%6s%6s%6s%5s\n",
1446 "Name",
1447 "Size",
1448 "Requests",
1449 "Fail",
1450 "Releases",
1451 "Pgreq",
1452 "Pgrel",
1453 "Npage",
1454 "Hiwat",
1455 "Minpg",
1456 "Maxpg",
1457 "Idle");
1458 else
1459 db_printf("%-10s %18s %18s\n",
1460 "Name", "Address", "Allocator");
1461
1462 TAILQ_FOREACH(pp, &pool_head, pr_poollist) {
1463 if (mode == 'a') {
1464 db_printf("%-10s %18p %18p\n", pp->pr_wchan, pp,
1465 pp->pr_alloc);
1466 continue;
1467 }
1468
1469 if (!pp->pr_nget)
1470 continue;
1471
1472 if (pp->pr_maxpages == UINT_MAX)
1473 snprintf(maxp, sizeof maxp, "inf");
1474 else
1475 snprintf(maxp, sizeof maxp, "%u", pp->pr_maxpages);
1476
1477 #define PRWORD(ovflw, fmt, width, fixed, val) do { \
1478 (ovflw) += db_printf((fmt), \
1479 (width) - (fixed) - (ovflw) > 0 ? \
1480 (width) - (fixed) - (ovflw) : 0, \
1481 (val)) - (width); \
1482 if ((ovflw) < 0) \
1483 (ovflw) = 0; \
1484 } while (0)
1485
1486 ovflw = 0;
1487 PRWORD(ovflw, "%-*s", 10, 0, pp->pr_wchan);
1488 PRWORD(ovflw, " %*u", 4, 1, pp->pr_size);
1489 PRWORD(ovflw, " %*lu", 9, 1, pp->pr_nget);
1490 PRWORD(ovflw, " %*lu", 5, 1, pp->pr_nfail);
1491 PRWORD(ovflw, " %*lu", 9, 1, pp->pr_nput);
1492 PRWORD(ovflw, " %*lu", 6, 1, pp->pr_npagealloc);
1493 PRWORD(ovflw, " %*lu", 6, 1, pp->pr_npagefree);
1494 PRWORD(ovflw, " %*d", 6, 1, pp->pr_npages);
1495 PRWORD(ovflw, " %*d", 6, 1, pp->pr_hiwat);
1496 PRWORD(ovflw, " %*d", 6, 1, pp->pr_minpages);
1497 PRWORD(ovflw, " %*s", 6, 1, maxp);
1498 PRWORD(ovflw, " %*lu\n", 5, 1, pp->pr_nidle);
1499 }
1500 }
1501
1502 int
1503 pool_chk_page(struct pool *pp, const char *label, struct pool_item_header *ph)
1504 {
1505 struct pool_item *pi;
1506 caddr_t page;
1507 int n;
1508
1509 page = (caddr_t)((u_long)ph & pp->pr_alloc->pa_pagemask);
1510 if (page != ph->ph_page &&
1511 (pp->pr_roflags & PR_PHINPAGE) != 0) {
1512 if (label != NULL)
1513 printf("%s: ", label);
1514 printf("pool(%p:%s): page inconsistency: page %p;"
1515 " at page head addr %p (p %p)\n", pp,
1516 pp->pr_wchan, ph->ph_page,
1517 ph, page);
1518 return 1;
1519 }
1520
1521 for (pi = TAILQ_FIRST(&ph->ph_itemlist), n = 0;
1522 pi != NULL;
1523 pi = TAILQ_NEXT(pi,pi_list), n++) {
1524
1525 #ifdef DIAGNOSTIC
1526 if (pi->pi_magic != PI_MAGIC) {
1527 if (label != NULL)
1528 printf("%s: ", label);
1529 printf("pool(%s): free list modified: magic=%x;"
1530 " page %p; item ordinal %d;"
1531 " addr %p (p %p)\n",
1532 pp->pr_wchan, pi->pi_magic, ph->ph_page,
1533 n, pi, page);
1534 panic("pool");
1535 }
1536 #endif
1537 page =
1538 (caddr_t)((u_long)pi & pp->pr_alloc->pa_pagemask);
1539 if (page == ph->ph_page)
1540 continue;
1541
1542 if (label != NULL)
1543 printf("%s: ", label);
1544 printf("pool(%p:%s): page inconsistency: page %p;"
1545 " item ordinal %d; addr %p (p %p)\n", pp,
1546 pp->pr_wchan, ph->ph_page,
1547 n, pi, page);
1548 return 1;
1549 }
1550 return 0;
1551 }
1552
1553 int
1554 pool_chk(struct pool *pp, const char *label)
1555 {
1556 struct pool_item_header *ph;
1557 int r = 0;
1558
1559 simple_lock(&pp->pr_slock);
1560 LIST_FOREACH(ph, &pp->pr_emptypages, ph_pagelist) {
1561 r = pool_chk_page(pp, label, ph);
1562 if (r) {
1563 goto out;
1564 }
1565 }
1566 LIST_FOREACH(ph, &pp->pr_fullpages, ph_pagelist) {
1567 r = pool_chk_page(pp, label, ph);
1568 if (r) {
1569 goto out;
1570 }
1571 }
1572 LIST_FOREACH(ph, &pp->pr_partpages, ph_pagelist) {
1573 r = pool_chk_page(pp, label, ph);
1574 if (r) {
1575 goto out;
1576 }
1577 }
1578
1579 out:
1580 simple_unlock(&pp->pr_slock);
1581 return (r);
1582 }
1583 #endif
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593 void
1594 pool_cache_init(struct pool_cache *pc, struct pool *pp,
1595 int (*ctor)(void *, void *, int),
1596 void (*dtor)(void *, void *),
1597 void *arg)
1598 {
1599
1600 TAILQ_INIT(&pc->pc_grouplist);
1601 simple_lock_init(&pc->pc_slock);
1602
1603 pc->pc_allocfrom = NULL;
1604 pc->pc_freeto = NULL;
1605 pc->pc_pool = pp;
1606
1607 pc->pc_ctor = ctor;
1608 pc->pc_dtor = dtor;
1609 pc->pc_arg = arg;
1610
1611 pc->pc_hits = 0;
1612 pc->pc_misses = 0;
1613
1614 pc->pc_ngroups = 0;
1615
1616 pc->pc_nitems = 0;
1617
1618 simple_lock(&pp->pr_slock);
1619 TAILQ_INSERT_TAIL(&pp->pr_cachelist, pc, pc_poollist);
1620 simple_unlock(&pp->pr_slock);
1621 }
1622
1623
1624
1625
1626
1627
1628 void
1629 pool_cache_destroy(struct pool_cache *pc)
1630 {
1631 struct pool *pp = pc->pc_pool;
1632
1633
1634 pool_cache_invalidate(pc);
1635
1636
1637 simple_lock(&pp->pr_slock);
1638 TAILQ_REMOVE(&pp->pr_cachelist, pc, pc_poollist);
1639 simple_unlock(&pp->pr_slock);
1640 }
1641
1642 static __inline void *
1643 pcg_get(struct pool_cache_group *pcg)
1644 {
1645 void *object;
1646 u_int idx;
1647
1648 KASSERT(pcg->pcg_avail <= PCG_NOBJECTS);
1649 KASSERT(pcg->pcg_avail != 0);
1650 idx = --pcg->pcg_avail;
1651
1652 KASSERT(pcg->pcg_objects[idx] != NULL);
1653 object = pcg->pcg_objects[idx];
1654 pcg->pcg_objects[idx] = NULL;
1655
1656 return (object);
1657 }
1658
1659 static __inline void
1660 pcg_put(struct pool_cache_group *pcg, void *object)
1661 {
1662 u_int idx;
1663
1664 KASSERT(pcg->pcg_avail < PCG_NOBJECTS);
1665 idx = pcg->pcg_avail++;
1666
1667 KASSERT(pcg->pcg_objects[idx] == NULL);
1668 pcg->pcg_objects[idx] = object;
1669 }
1670
1671
1672
1673
1674
1675
1676 void *
1677 pool_cache_get(struct pool_cache *pc, int flags)
1678 {
1679 struct pool_cache_group *pcg;
1680 void *object;
1681
1682 #ifdef LOCKDEBUG
1683 if (flags & PR_WAITOK)
1684 simple_lock_only_held(NULL, "pool_cache_get(PR_WAITOK)");
1685 #endif
1686
1687 simple_lock(&pc->pc_slock);
1688
1689 if ((pcg = pc->pc_allocfrom) == NULL) {
1690 TAILQ_FOREACH(pcg, &pc->pc_grouplist, pcg_list) {
1691 if (pcg->pcg_avail != 0) {
1692 pc->pc_allocfrom = pcg;
1693 goto have_group;
1694 }
1695 }
1696
1697
1698
1699
1700
1701
1702
1703 pc->pc_misses++;
1704 simple_unlock(&pc->pc_slock);
1705 object = pool_get(pc->pc_pool, flags);
1706 if (object != NULL && pc->pc_ctor != NULL) {
1707 if ((*pc->pc_ctor)(pc->pc_arg, object, flags) != 0) {
1708 pool_put(pc->pc_pool, object);
1709 return (NULL);
1710 }
1711 }
1712 return (object);
1713 }
1714
1715 have_group:
1716 pc->pc_hits++;
1717 pc->pc_nitems--;
1718 object = pcg_get(pcg);
1719
1720 if (pcg->pcg_avail == 0)
1721 pc->pc_allocfrom = NULL;
1722
1723 simple_unlock(&pc->pc_slock);
1724
1725 return (object);
1726 }
1727
1728
1729
1730
1731
1732
1733 void
1734 pool_cache_put(struct pool_cache *pc, void *object)
1735 {
1736 struct pool_cache_group *pcg;
1737 int s;
1738
1739 simple_lock(&pc->pc_slock);
1740
1741 if ((pcg = pc->pc_freeto) == NULL) {
1742 TAILQ_FOREACH(pcg, &pc->pc_grouplist, pcg_list) {
1743 if (pcg->pcg_avail != PCG_NOBJECTS) {
1744 pc->pc_freeto = pcg;
1745 goto have_group;
1746 }
1747 }
1748
1749
1750
1751
1752
1753 simple_unlock(&pc->pc_slock);
1754 s = splvm();
1755 pcg = pool_get(&pcgpool, PR_NOWAIT);
1756 splx(s);
1757 if (pcg != NULL) {
1758 memset(pcg, 0, sizeof(*pcg));
1759 simple_lock(&pc->pc_slock);
1760 pc->pc_ngroups++;
1761 TAILQ_INSERT_TAIL(&pc->pc_grouplist, pcg, pcg_list);
1762 if (pc->pc_freeto == NULL)
1763 pc->pc_freeto = pcg;
1764 goto have_group;
1765 }
1766
1767
1768
1769
1770
1771 pool_cache_destruct_object(pc, object);
1772 return;
1773 }
1774
1775 have_group:
1776 pc->pc_nitems++;
1777 pcg_put(pcg, object);
1778
1779 if (pcg->pcg_avail == PCG_NOBJECTS)
1780 pc->pc_freeto = NULL;
1781
1782 simple_unlock(&pc->pc_slock);
1783 }
1784
1785
1786
1787
1788
1789
1790
1791 void
1792 pool_cache_destruct_object(struct pool_cache *pc, void *object)
1793 {
1794
1795 if (pc->pc_dtor != NULL)
1796 (*pc->pc_dtor)(pc->pc_arg, object);
1797 pool_put(pc->pc_pool, object);
1798 }
1799
1800
1801
1802
1803
1804
1805
1806 void
1807 pool_cache_do_invalidate(struct pool_cache *pc, int free_groups,
1808 void (*putit)(struct pool *, void *))
1809 {
1810 struct pool_cache_group *pcg, *npcg;
1811 void *object;
1812 int s;
1813
1814 for (pcg = TAILQ_FIRST(&pc->pc_grouplist); pcg != NULL;
1815 pcg = npcg) {
1816 npcg = TAILQ_NEXT(pcg, pcg_list);
1817 while (pcg->pcg_avail != 0) {
1818 pc->pc_nitems--;
1819 object = pcg_get(pcg);
1820 if (pcg->pcg_avail == 0 && pc->pc_allocfrom == pcg)
1821 pc->pc_allocfrom = NULL;
1822 if (pc->pc_dtor != NULL)
1823 (*pc->pc_dtor)(pc->pc_arg, object);
1824 (*putit)(pc->pc_pool, object);
1825 }
1826 if (free_groups) {
1827 pc->pc_ngroups--;
1828 TAILQ_REMOVE(&pc->pc_grouplist, pcg, pcg_list);
1829 if (pc->pc_freeto == pcg)
1830 pc->pc_freeto = NULL;
1831 s = splvm();
1832 pool_put(&pcgpool, pcg);
1833 splx(s);
1834 }
1835 }
1836 }
1837
1838
1839
1840
1841
1842
1843
1844 void
1845 pool_cache_invalidate(struct pool_cache *pc)
1846 {
1847
1848 simple_lock(&pc->pc_slock);
1849 pool_cache_do_invalidate(pc, 0, pool_put);
1850 simple_unlock(&pc->pc_slock);
1851 }
1852
1853
1854
1855
1856
1857
1858 void
1859 pool_cache_reclaim(struct pool_cache *pc)
1860 {
1861
1862 simple_lock(&pc->pc_slock);
1863 pool_cache_do_invalidate(pc, 1, pool_do_put);
1864 simple_unlock(&pc->pc_slock);
1865 }
1866
1867
1868
1869
1870
1871
1872
1873 int
1874 sysctl_dopool(int *name, u_int namelen, char *where, size_t *sizep)
1875 {
1876 struct pool *pp, *foundpool = NULL;
1877 size_t buflen = where != NULL ? *sizep : 0;
1878 int npools = 0, s;
1879 unsigned int lookfor;
1880 size_t len;
1881
1882 switch (*name) {
1883 case KERN_POOL_NPOOLS:
1884 if (namelen != 1 || buflen != sizeof(int))
1885 return (EINVAL);
1886 lookfor = 0;
1887 break;
1888 case KERN_POOL_NAME:
1889 if (namelen != 2 || buflen < 1)
1890 return (EINVAL);
1891 lookfor = name[1];
1892 break;
1893 case KERN_POOL_POOL:
1894 if (namelen != 2 || buflen != sizeof(struct pool))
1895 return (EINVAL);
1896 lookfor = name[1];
1897 break;
1898 default:
1899 return (EINVAL);
1900 }
1901
1902 s = splvm();
1903 simple_lock(&pool_head_slock);
1904
1905 TAILQ_FOREACH(pp, &pool_head, pr_poollist) {
1906 npools++;
1907 if (lookfor == pp->pr_serial) {
1908 foundpool = pp;
1909 break;
1910 }
1911 }
1912
1913 simple_unlock(&pool_head_slock);
1914 splx(s);
1915
1916 if (*name != KERN_POOL_NPOOLS && foundpool == NULL)
1917 return (ENOENT);
1918
1919 switch (*name) {
1920 case KERN_POOL_NPOOLS:
1921 return copyout(&npools, where, buflen);
1922 case KERN_POOL_NAME:
1923 len = strlen(foundpool->pr_wchan) + 1;
1924 if (*sizep < len)
1925 return (ENOMEM);
1926 *sizep = len;
1927 return copyout(foundpool->pr_wchan, where, len);
1928 case KERN_POOL_POOL:
1929 return copyout(foundpool, where, buflen);
1930 }
1931
1932 return (0);
1933 }
1934
1935
1936
1937
1938
1939
1940 void *pool_page_alloc_oldnointr(struct pool *, int);
1941 void pool_page_free_oldnointr(struct pool *, void *);
1942 void *pool_page_alloc(struct pool *, int);
1943 void pool_page_free(struct pool *, void *);
1944
1945
1946 struct pool_allocator pool_allocator_oldnointr = {
1947 pool_page_alloc_oldnointr, pool_page_free_oldnointr, 0,
1948 };
1949
1950
1951 struct pool_allocator pool_allocator_nointr = {
1952 pool_page_alloc, pool_page_free, 0,
1953 };
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970 void *
1971 pool_allocator_alloc(struct pool *pp, int flags)
1972 {
1973
1974 return (pp->pr_alloc->pa_alloc(pp, flags));
1975 }
1976
1977 void
1978 pool_allocator_free(struct pool *pp, void *v)
1979 {
1980 struct pool_allocator *pa = pp->pr_alloc;
1981 int s;
1982
1983 (*pa->pa_free)(pp, v);
1984
1985 s = splvm();
1986 simple_lock(&pa->pa_slock);
1987 if ((pa->pa_flags & PA_WANT) == 0) {
1988 simple_unlock(&pa->pa_slock);
1989 splx(s);
1990 return;
1991 }
1992
1993 TAILQ_FOREACH(pp, &pa->pa_list, pr_alloc_list) {
1994 simple_lock(&pp->pr_slock);
1995 if ((pp->pr_flags & PR_WANTED) != 0) {
1996 pp->pr_flags &= ~PR_WANTED;
1997 wakeup(pp);
1998 }
1999 simple_unlock(&pp->pr_slock);
2000 }
2001 pa->pa_flags &= ~PA_WANT;
2002 simple_unlock(&pa->pa_slock);
2003 splx(s);
2004 }
2005
2006 void *
2007 pool_page_alloc(struct pool *pp, int flags)
2008 {
2009 boolean_t waitok = (flags & PR_WAITOK) ? TRUE : FALSE;
2010
2011 return (uvm_km_getpage(waitok));
2012 }
2013
2014 void
2015 pool_page_free(struct pool *pp, void *v)
2016 {
2017
2018 uvm_km_putpage(v);
2019 }
2020
2021 void *
2022 pool_page_alloc_oldnointr(struct pool *pp, int flags)
2023 {
2024 boolean_t waitok = (flags & PR_WAITOK) ? TRUE : FALSE;
2025
2026 splassert(IPL_NONE);
2027
2028 return ((void *)uvm_km_alloc_poolpage1(kernel_map, uvm.kernel_object,
2029 waitok));
2030 }
2031
2032 void
2033 pool_page_free_oldnointr(struct pool *pp, void *v)
2034 {
2035 splassert(IPL_NONE);
2036
2037 uvm_km_free_poolpage1(kernel_map, (vaddr_t)v);
2038 }