This source file includes following definitions.
- uvm_wait
- uvmpd_tune
- uvm_pageout
- uvm_aiodone_daemon
- uvmpd_scan_inactive
- uvmpd_scan
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
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74 #include <sys/param.h>
75 #include <sys/proc.h>
76 #include <sys/systm.h>
77 #include <sys/kernel.h>
78 #include <sys/pool.h>
79 #include <sys/buf.h>
80 #include <sys/vnode.h>
81
82 #include <uvm/uvm.h>
83
84
85
86
87
88
89
90
91 #define UVMPD_NUMDIRTYREACTS 16
92
93
94
95
96
97
98 static void uvmpd_scan(void);
99 static boolean_t uvmpd_scan_inactive(struct pglist *);
100 static void uvmpd_tune(void);
101
102
103
104
105
106
107
108
109 void
110 uvm_wait(wmsg)
111 const char *wmsg;
112 {
113 int timo = 0;
114 int s = splbio();
115
116
117
118
119
120 if (curproc == uvm.pagedaemon_proc) {
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138 printf("pagedaemon: deadlock detected!\n");
139 timo = hz >> 3;
140 #if defined(DEBUG)
141
142 panic("pagedaemon deadlock");
143 #endif
144 }
145
146 simple_lock(&uvm.pagedaemon_lock);
147 wakeup(&uvm.pagedaemon);
148 UVM_UNLOCK_AND_WAIT(&uvmexp.free, &uvm.pagedaemon_lock, FALSE, wmsg,
149 timo);
150
151 splx(s);
152 }
153
154
155
156
157
158
159
160
161
162 static void
163 uvmpd_tune()
164 {
165 UVMHIST_FUNC("uvmpd_tune"); UVMHIST_CALLED(pdhist);
166
167 uvmexp.freemin = uvmexp.npages / 30;
168
169
170
171 uvmexp.freemin = max(uvmexp.freemin, (16*1024) >> PAGE_SHIFT);
172 uvmexp.freemin = min(uvmexp.freemin, (512*1024) >> PAGE_SHIFT);
173
174
175 if (uvmexp.freemin < uvmexp.reserve_kernel + 1)
176 uvmexp.freemin = uvmexp.reserve_kernel + 1;
177
178 uvmexp.freetarg = (uvmexp.freemin * 4) / 3;
179 if (uvmexp.freetarg <= uvmexp.freemin)
180 uvmexp.freetarg = uvmexp.freemin + 1;
181
182
183
184 uvmexp.wiredmax = uvmexp.npages / 3;
185 UVMHIST_LOG(pdhist, "<- done, freemin=%ld, freetarg=%ld, wiredmax=%ld",
186 uvmexp.freemin, uvmexp.freetarg, uvmexp.wiredmax, 0);
187 }
188
189
190
191
192
193 void
194 uvm_pageout(void *arg)
195 {
196 int npages = 0;
197 UVMHIST_FUNC("uvm_pageout"); UVMHIST_CALLED(pdhist);
198
199 UVMHIST_LOG(pdhist,"<starting uvm pagedaemon>", 0, 0, 0, 0);
200
201
202
203
204
205 uvm.pagedaemon_proc = curproc;
206 (void) spl0();
207 uvm_lock_pageq();
208 npages = uvmexp.npages;
209 uvmpd_tune();
210 uvm_unlock_pageq();
211
212
213
214
215
216 for (;;) {
217 simple_lock(&uvm.pagedaemon_lock);
218
219 UVMHIST_LOG(pdhist," <<SLEEPING>>",0,0,0,0);
220 UVM_UNLOCK_AND_WAIT(&uvm.pagedaemon,
221 &uvm.pagedaemon_lock, FALSE, "pgdaemon", 0);
222 uvmexp.pdwoke++;
223 UVMHIST_LOG(pdhist," <<WOKE UP>>",0,0,0,0);
224
225
226
227
228
229 uvm_lock_pageq();
230 if (npages != uvmexp.npages) {
231 npages = uvmexp.npages;
232 uvmpd_tune();
233 }
234
235 uvmexp.inactarg = (uvmexp.active + uvmexp.inactive) / 3;
236 if (uvmexp.inactarg <= uvmexp.freetarg) {
237 uvmexp.inactarg = uvmexp.freetarg + 1;
238 }
239
240 UVMHIST_LOG(pdhist," free/ftarg=%ld/%ld, inact/itarg=%ld/%ld",
241 uvmexp.free, uvmexp.freetarg, uvmexp.inactive,
242 uvmexp.inactarg);
243
244
245
246
247
248 #ifdef UBC
249 if (uvmexp.free + uvmexp.paging < uvmexp.freetarg ||
250 uvmexp.inactive < uvmexp.inactarg ||
251 uvm_pgcnt_vnode >
252 (uvmexp.active + uvmexp.inactive + uvmexp.wired +
253 uvmexp.free) * 13 / 16) {
254 #else
255 if (uvmexp.free < uvmexp.freetarg ||
256 uvmexp.inactive < uvmexp.inactarg) {
257 #endif
258 uvmpd_scan();
259 }
260
261
262
263
264
265
266 if (uvmexp.free > uvmexp.reserve_kernel ||
267 uvmexp.paging == 0) {
268 wakeup(&uvmexp.free);
269 }
270
271
272
273
274
275 uvm_unlock_pageq();
276 }
277
278 }
279
280
281
282
283
284
285 void
286 uvm_aiodone_daemon(void *arg)
287 {
288 int s, free;
289 struct buf *bp, *nbp;
290 UVMHIST_FUNC("uvm_aiodoned"); UVMHIST_CALLED(pdhist);
291
292 for (;;) {
293
294
295
296
297
298
299
300 s = splbio();
301 simple_lock(&uvm.aiodoned_lock);
302 if (TAILQ_FIRST(&uvm.aio_done) == NULL) {
303 UVMHIST_LOG(pdhist," <<SLEEPING>>",0,0,0,0);
304 UVM_UNLOCK_AND_WAIT(&uvm.aiodoned,
305 &uvm.aiodoned_lock, FALSE, "aiodoned", 0);
306 UVMHIST_LOG(pdhist," <<WOKE UP>>",0,0,0,0);
307
308
309 simple_lock(&uvm.aiodoned_lock);
310 }
311
312
313
314
315
316 bp = TAILQ_FIRST(&uvm.aio_done);
317 if (bp) {
318 TAILQ_INIT(&uvm.aio_done);
319 }
320
321 simple_unlock(&uvm.aiodoned_lock);
322 splx(s);
323
324
325
326
327
328 free = uvmexp.free;
329 while (bp != NULL) {
330 if (bp->b_flags & B_PDAEMON) {
331 uvmexp.paging -= bp->b_bufsize >> PAGE_SHIFT;
332 }
333 nbp = TAILQ_NEXT(bp, b_freelist);
334 s = splbio();
335 (*bp->b_iodone)(bp);
336 splx(s);
337 bp = nbp;
338 }
339 if (free <= uvmexp.reserve_kernel) {
340 s = uvm_lock_fpageq();
341 wakeup(&uvm.pagedaemon);
342 uvm_unlock_fpageq(s);
343 } else {
344 simple_lock(&uvm.pagedaemon_lock);
345 wakeup(&uvmexp.free);
346 simple_unlock(&uvm.pagedaemon_lock);
347 }
348 }
349 }
350
351
352
353
354
355
356
357
358
359
360
361
362
363 static boolean_t
364 uvmpd_scan_inactive(pglst)
365 struct pglist *pglst;
366 {
367 boolean_t retval = FALSE;
368 int s, free, result;
369 struct vm_page *p, *nextpg;
370 struct uvm_object *uobj;
371 struct vm_page *pps[MAXBSIZE >> PAGE_SHIFT], **ppsp;
372 int npages;
373 struct vm_page *swpps[MAXBSIZE >> PAGE_SHIFT];
374 int swnpages, swcpages;
375 int swslot;
376 struct vm_anon *anon;
377 boolean_t swap_backed;
378 vaddr_t start;
379 int dirtyreacts;
380 UVMHIST_FUNC("uvmpd_scan_inactive"); UVMHIST_CALLED(pdhist);
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396 swslot = 0;
397 swnpages = swcpages = 0;
398 free = 0;
399 dirtyreacts = 0;
400
401 for (p = TAILQ_FIRST(pglst); p != NULL || swslot != 0; p = nextpg) {
402
403
404
405
406
407
408 uobj = NULL;
409 anon = NULL;
410
411 if (p) {
412
413
414
415
416
417
418 s = uvm_lock_fpageq();
419 free = uvmexp.free;
420 uvm_unlock_fpageq(s);
421
422 if (free + uvmexp.paging >= uvmexp.freetarg << 2 ||
423 dirtyreacts == UVMPD_NUMDIRTYREACTS) {
424 UVMHIST_LOG(pdhist," met free target: "
425 "exit loop", 0, 0, 0, 0);
426 retval = TRUE;
427
428 if (swslot == 0) {
429
430 break;
431 }
432
433
434 p = NULL;
435 }
436 }
437
438 if (p) {
439
440
441
442
443 uvmexp.pdscans++;
444 nextpg = TAILQ_NEXT(p, pageq);
445
446
447
448
449
450
451
452
453 if (pmap_is_referenced(p)) {
454 uvm_pageactivate(p);
455 uvmexp.pdreact++;
456 continue;
457 }
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476 if ((p->pg_flags & PQ_ANON) || p->uobject == NULL) {
477 anon = p->uanon;
478 KASSERT(anon != NULL);
479 if (!simple_lock_try(&anon->an_lock)) {
480
481 continue;
482 }
483
484
485
486
487
488
489 if ((p->pg_flags & PQ_ANON) == 0) {
490 KASSERT(p->loan_count > 0);
491 p->loan_count--;
492 atomic_setbits_int(&p->pg_flags,
493 PQ_ANON);
494
495 }
496 if (p->pg_flags & PG_BUSY) {
497 simple_unlock(&anon->an_lock);
498 uvmexp.pdbusy++;
499
500 continue;
501 }
502 uvmexp.pdanscan++;
503 } else {
504 uobj = p->uobject;
505 KASSERT(uobj != NULL);
506 if (!simple_lock_try(&uobj->vmobjlock)) {
507
508 continue;
509 }
510 if (p->pg_flags & PG_BUSY) {
511 simple_unlock(&uobj->vmobjlock);
512 uvmexp.pdbusy++;
513
514 continue;
515 }
516 uvmexp.pdobscan++;
517 }
518
519
520
521
522
523
524
525 if (p->pg_flags & PG_CLEAN) {
526 if (p->pg_flags & PQ_SWAPBACKED) {
527
528 simple_lock(&uvm.swap_data_lock);
529 uvmexp.swpgonly++;
530 simple_unlock(&uvm.swap_data_lock);
531 }
532
533
534 pmap_page_protect(p, VM_PROT_NONE);
535 uvm_pagefree(p);
536 uvmexp.pdfreed++;
537
538 if (anon) {
539
540
541
542
543
544
545 KASSERT(anon->an_swslot != 0);
546
547
548 anon->an_page = NULL;
549 simple_unlock(&anon->an_lock);
550 } else {
551
552
553 simple_unlock(&uobj->vmobjlock);
554 }
555 continue;
556 }
557
558
559
560
561
562
563 if (free + uvmexp.paging > uvmexp.freetarg << 2) {
564 if (anon) {
565 simple_unlock(&anon->an_lock);
566 } else {
567 simple_unlock(&uobj->vmobjlock);
568 }
569 continue;
570 }
571
572
573
574
575
576
577
578
579 KASSERT(uvmexp.swpgonly <= uvmexp.swpages);
580 if ((p->pg_flags & PQ_SWAPBACKED) &&
581 uvmexp.swpgonly == uvmexp.swpages) {
582 dirtyreacts++;
583 uvm_pageactivate(p);
584 if (anon) {
585 simple_unlock(&anon->an_lock);
586 } else {
587 simple_unlock(&uobj->vmobjlock);
588 }
589 continue;
590 }
591
592
593
594
595
596
597
598 KASSERT(uvmexp.swpginuse <= uvmexp.swpages);
599 if ((p->pg_flags & PQ_SWAPBACKED) &&
600 uvmexp.swpginuse == uvmexp.swpages) {
601
602 if ((p->pg_flags & PQ_ANON) &&
603 p->uanon->an_swslot) {
604 uvm_swap_free(p->uanon->an_swslot, 1);
605 p->uanon->an_swslot = 0;
606 }
607 if (p->pg_flags & PQ_AOBJ) {
608 uao_dropswap(p->uobject,
609 p->offset >> PAGE_SHIFT);
610 }
611 }
612
613
614
615
616
617
618
619
620
621
622 swap_backed = ((p->pg_flags & PQ_SWAPBACKED) != 0);
623 atomic_setbits_int(&p->pg_flags, PG_BUSY);
624 UVM_PAGE_OWN(p, "scan_inactive");
625 pmap_page_protect(p, VM_PROT_READ);
626 uvmexp.pgswapout++;
627
628
629
630
631
632
633 if (swap_backed) {
634
635
636
637
638
639 if (anon) {
640 if (anon->an_swslot) {
641 uvm_swap_free(anon->an_swslot,
642 1);
643 anon->an_swslot = 0;
644 }
645 } else {
646 uao_dropswap(uobj,
647 p->offset >> PAGE_SHIFT);
648 }
649
650
651
652
653
654 if (swslot == 0) {
655 swnpages = MAXBSIZE >> PAGE_SHIFT;
656 swslot = uvm_swap_alloc(&swnpages,
657 TRUE);
658 if (swslot == 0) {
659
660 atomic_clearbits_int(
661 &p->pg_flags,
662 PG_BUSY);
663 UVM_PAGE_OWN(p, NULL);
664 if (anon)
665 simple_unlock(
666 &anon->an_lock);
667 else
668 simple_unlock(
669 &uobj->vmobjlock);
670 continue;
671 }
672 swcpages = 0;
673 }
674
675
676
677
678
679 swpps[swcpages] = p;
680 if (anon)
681 anon->an_swslot = swslot + swcpages;
682 else
683 uao_set_swslot(uobj,
684 p->offset >> PAGE_SHIFT,
685 swslot + swcpages);
686 swcpages++;
687 }
688 } else {
689
690
691 swap_backed = TRUE;
692 }
693
694
695
696
697
698
699
700
701
702
703
704 if (swap_backed) {
705 if (p) {
706 if (anon)
707 simple_unlock(&anon->an_lock);
708 else
709 simple_unlock(&uobj->vmobjlock);
710
711
712 if (swcpages < swnpages)
713 continue;
714 }
715
716
717 npages = swcpages;
718 ppsp = swpps;
719
720 start = (vaddr_t) swslot;
721
722
723
724 if (swcpages < swnpages) {
725 uvm_swap_free(swslot + swcpages,
726 (swnpages - swcpages));
727 }
728 } else {
729
730 ppsp = pps;
731 npages = sizeof(pps) / sizeof(struct vm_page *);
732
733 start = 0;
734 }
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758 uvmexp.pdpageouts++;
759 result = uvm_pager_put(swap_backed ? NULL : uobj, p,
760 &ppsp, &npages, PGO_ALLPAGES|PGO_PDFREECLUST, start, 0);
761
762
763
764
765
766
767
768
769 if (swap_backed)
770 swslot = 0;
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785 if (result == VM_PAGER_PEND) {
786 uvmexp.paging += npages;
787 uvm_lock_pageq();
788 uvmexp.pdpending++;
789 if (p) {
790 if (p->pg_flags & PQ_INACTIVE)
791 nextpg = TAILQ_NEXT(p, pageq);
792 else
793 nextpg = TAILQ_FIRST(pglst);
794 } else {
795 nextpg = NULL;
796 }
797 continue;
798 }
799
800 #ifdef UBC
801 if (result == VM_PAGER_ERROR &&
802 curproc == uvm.pagedaemon_proc) {
803 uvm_lock_pageq();
804 nextpg = TAILQ_NEXT(p, pageq);
805 uvm_pageactivate(p);
806 continue;
807 }
808 #endif
809
810
811
812
813
814 if (p) {
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838 if (swap_backed) {
839 if (anon)
840 simple_lock(&anon->an_lock);
841 else
842 simple_lock(&uobj->vmobjlock);
843 }
844
845 #ifdef DIAGNOSTIC
846 if (result == VM_PAGER_UNLOCK)
847 panic("pagedaemon: pageout returned "
848 "invalid 'unlock' code");
849 #endif
850
851
852 if (p->pg_flags & PG_WANTED)
853
854 wakeup(p);
855
856 atomic_clearbits_int(&p->pg_flags, PG_BUSY|PG_WANTED);
857 UVM_PAGE_OWN(p, NULL);
858
859
860 if (p->pg_flags & PG_RELEASED) {
861 if (anon) {
862
863 anon->an_page = NULL;
864
865 simple_unlock(&anon->an_lock);
866 uvm_anfree(anon);
867 pmap_page_protect(p, VM_PROT_NONE);
868 anon = NULL;
869 uvm_lock_pageq();
870 nextpg = TAILQ_NEXT(p, pageq);
871
872 uvm_pagefree(p);
873
874 } else {
875
876
877
878
879
880
881
882
883 if (!uobj->pgops->pgo_releasepg(p,
884 &nextpg))
885
886 uobj = NULL;
887
888
889
890
891
892
893 uvm_lock_pageq();
894 }
895 } else {
896 uvm_lock_pageq();
897 nextpg = TAILQ_NEXT(p, pageq);
898 if (result != VM_PAGER_OK) {
899
900 if (result != VM_PAGER_AGAIN)
901 uvm_pageactivate(p);
902 pmap_clear_reference(p);
903
904
905 } else {
906
907 pmap_clear_reference(p);
908 pmap_clear_modify(p);
909 atomic_setbits_int(&p->pg_flags,
910 PG_CLEAN);
911 }
912 }
913
914
915
916
917
918
919
920
921
922 if (anon)
923 simple_unlock(&anon->an_lock);
924 else if (uobj)
925 simple_unlock(&uobj->vmobjlock);
926
927 } else {
928
929
930
931
932
933
934 nextpg = NULL;
935
936
937
938
939
940
941 uvm_lock_pageq();
942 }
943
944 if (nextpg && (nextpg->pg_flags & PQ_INACTIVE) == 0) {
945 nextpg = TAILQ_FIRST(pglst);
946 }
947 }
948 return (retval);
949 }
950
951
952
953
954
955
956
957 void
958 uvmpd_scan()
959 {
960 int s, free, inactive_shortage, swap_shortage, pages_freed;
961 struct vm_page *p, *nextpg;
962 struct uvm_object *uobj;
963 boolean_t got_it;
964 UVMHIST_FUNC("uvmpd_scan"); UVMHIST_CALLED(pdhist);
965
966 uvmexp.pdrevs++;
967 uobj = NULL;
968
969
970
971
972 s = uvm_lock_fpageq();
973 free = uvmexp.free;
974 uvm_unlock_fpageq(s);
975
976 #ifndef __SWAP_BROKEN
977
978
979
980
981 if (free < uvmexp.freetarg) {
982 uvmexp.pdswout++;
983 UVMHIST_LOG(pdhist," free %ld < target %ld: swapout", free,
984 uvmexp.freetarg, 0, 0);
985 uvm_unlock_pageq();
986 uvm_swapout_threads();
987 uvm_lock_pageq();
988
989 }
990 #endif
991
992
993
994
995
996
997
998
999 UVMHIST_LOG(pdhist, " starting 'free' loop",0,0,0,0);
1000
1001
1002
1003
1004
1005
1006 got_it = FALSE;
1007 pages_freed = uvmexp.pdfreed;
1008 if ((uvmexp.pdrevs & 1) != 0 && uvmexp.nswapdev != 0)
1009 got_it = uvmpd_scan_inactive(&uvm.page_inactive_swp);
1010 if (!got_it)
1011 got_it = uvmpd_scan_inactive(&uvm.page_inactive_obj);
1012 if (!got_it && (uvmexp.pdrevs & 1) == 0 && uvmexp.nswapdev != 0)
1013 (void) uvmpd_scan_inactive(&uvm.page_inactive_swp);
1014 pages_freed = uvmexp.pdfreed - pages_freed;
1015
1016
1017
1018
1019
1020
1021 inactive_shortage = uvmexp.inactarg - uvmexp.inactive;
1022
1023
1024
1025
1026
1027
1028 swap_shortage = 0;
1029 if (uvmexp.free < uvmexp.freetarg &&
1030 uvmexp.swpginuse == uvmexp.swpages &&
1031 uvmexp.swpgonly < uvmexp.swpages &&
1032 pages_freed == 0) {
1033 swap_shortage = uvmexp.freetarg - uvmexp.free;
1034 }
1035
1036 UVMHIST_LOG(pdhist, " loop 2: inactive_shortage=%ld swap_shortage=%ld",
1037 inactive_shortage, swap_shortage,0,0);
1038 for (p = TAILQ_FIRST(&uvm.page_active);
1039 p != NULL && (inactive_shortage > 0 || swap_shortage > 0);
1040 p = nextpg) {
1041 nextpg = TAILQ_NEXT(p, pageq);
1042 if (p->pg_flags & PG_BUSY)
1043 continue;
1044
1045
1046
1047
1048
1049 if ((p->pg_flags & PQ_ANON) || p->uobject == NULL) {
1050 KASSERT(p->uanon != NULL);
1051 if (!simple_lock_try(&p->uanon->an_lock))
1052 continue;
1053
1054
1055 if ((p->pg_flags & PQ_ANON) == 0) {
1056 KASSERT(p->loan_count > 0);
1057 p->loan_count--;
1058 atomic_setbits_int(&p->pg_flags, PQ_ANON);
1059 }
1060 } else {
1061 if (!simple_lock_try(&p->uobject->vmobjlock))
1062 continue;
1063 }
1064
1065
1066
1067
1068
1069 if ((p->pg_flags & PG_BUSY) != 0) {
1070 if (p->pg_flags & PQ_ANON)
1071 simple_unlock(&p->uanon->an_lock);
1072 else
1073 simple_unlock(&p->uobject->vmobjlock);
1074 continue;
1075 }
1076
1077
1078
1079
1080
1081
1082 if (swap_shortage > 0) {
1083 if ((p->pg_flags & PQ_ANON) && p->uanon->an_swslot) {
1084 uvm_swap_free(p->uanon->an_swslot, 1);
1085 p->uanon->an_swslot = 0;
1086 atomic_clearbits_int(&p->pg_flags, PG_CLEAN);
1087 swap_shortage--;
1088 }
1089 if (p->pg_flags & PQ_AOBJ) {
1090 int slot = uao_set_swslot(p->uobject,
1091 p->offset >> PAGE_SHIFT, 0);
1092 if (slot) {
1093 uvm_swap_free(slot, 1);
1094 atomic_clearbits_int(&p->pg_flags,
1095 PG_CLEAN);
1096 swap_shortage--;
1097 }
1098 }
1099 }
1100
1101
1102
1103
1104
1105
1106 if (inactive_shortage > 0) {
1107 pmap_page_protect(p, VM_PROT_NONE);
1108
1109 uvm_pagedeactivate(p);
1110 uvmexp.pddeact++;
1111 inactive_shortage--;
1112 }
1113 if (p->pg_flags & PQ_ANON)
1114 simple_unlock(&p->uanon->an_lock);
1115 else
1116 simple_unlock(&p->uobject->vmobjlock);
1117 }
1118 }