1 #include "stdinc.h"
2 #include "dat.h"
3 #include "fns.h"
4 
5 ulong lasttime[2];
6 int manualscheduling;
7 int l0quantum = 120;
8 int l1quantum = 120;
9 ulong lasticachechange;
10 
11 void
disksched(void)12 disksched(void)
13 {
14 	int p, nwrite, nflush, ndirty, tdirty, toflush;
15 	ulong t;
16 	vlong cflush;
17 	Stats *prev;
18 
19 	/*
20 	 * no locks because all the data accesses are atomic.
21 	 */
22 	t = time(0);
23 	if(manualscheduling){
24 		lasticachechange = t;
25 		return;
26 	}
27 
28 	if(t-lasttime[0] < l0quantum){
29 		/* level-0 disk access going on */
30 		p = icachedirtyfrac();
31 		if(p < IcacheFrac*5/10){	/* can wait */
32 			icachesleeptime = SleepForever;
33 			lasticachechange = t;
34 		}else if(p > IcacheFrac*9/10){	/* can't wait */
35 			icachesleeptime = 0;
36 			lasticachechange = t;
37 		}else if(t-lasticachechange > 60){
38 			/* have minute worth of data for current rate */
39 			prev = &stathist[(stattime-60+nstathist)%nstathist];
40 
41 			/* # entries written to index cache */
42 			nwrite = stats.n[StatIcacheWrite] - prev->n[StatIcacheWrite];
43 
44 			/* # dirty entries in index cache */
45 			ndirty = stats.n[StatIcacheDirty] - prev->n[StatIcacheDirty];
46 
47 			/* # entries flushed to disk */
48 			nflush = nwrite - ndirty;
49 
50 			/* want to stay around 70% dirty */
51 			tdirty = (vlong)stats.n[StatIcacheSize]*700/1000;
52 
53 			/* assume nflush*icachesleeptime is a constant */
54 			cflush = (vlong)nflush*(icachesleeptime+1);
55 
56 			/* computer number entries to write in next minute */
57 			toflush = nwrite + (stats.n[StatIcacheDirty] - tdirty);
58 
59 			/* schedule for  that many */
60 			if(toflush <= 0 || cflush/toflush > 100000)
61 				icachesleeptime = SleepForever;
62 			else
63 				icachesleeptime = cflush/toflush;
64 		}
65 		arenasumsleeptime = SleepForever;
66 		return;
67 	}
68 	if(t-lasttime[1] < l1quantum){
69 		/* level-1 disk access (icache flush) going on */
70 		icachesleeptime = 0;
71 		arenasumsleeptime = SleepForever;
72 		return;
73 	}
74 	/* no disk access going on - no holds barred*/
75 	icachesleeptime = 0;
76 	arenasumsleeptime = 0;
77 }
78 
79 void
diskaccess(int level)80 diskaccess(int level)
81 {
82 	if(level < 0 || level >= nelem(lasttime)){
83 		fprint(2, "bad level in diskaccess; caller=%#p\n",
84 			getcallerpc(&level));
85 		return;
86 	}
87 	lasttime[level] = time(0);
88 }
89