slp.c

1800 # 1801 /* 1802 */ 1803 1804 #include "../param.h" 1805 #include "../user.h" 1806 #include "../proc.h" 1807 #include "../text.h" 1808 #include "../systm.h" 1809 #include "../file.h" 1810 #include "../inode.h" 1811 #include "../buf.h" 1812 1813 /* 1814 * Give up the processor till a wakeup occurs 1815 * on chan, at which time the process 1816 * enters the scheduling queue at priority pri. 1817 * The most important effect of pri is that when 1818 * pri<0 a signal cannot disturb the sleep; 1819 * if pri>=0 signals will be processed. 1820 * Callers of this routine must be prepared for 1821 * premature return, and check that the reason for 1822 * sleeping has gone away. 1823 */ 1824 sleep(chan, pri) 1825 { 1826 register *rp, s; 1827 1828 s = PS->integ; 1829 rp = u.u_procp; 1830 if(pri >= 0) { 1831 if(issig()) 1832 goto psig; 1833 spl6(); 1834 rp->p_wchan = chan; 1835 rp->p_stat = SWAIT; 1836 rp->p_pri = pri; 1837 spl0(); 1838 if(runin != 0) { 1839 runin = 0; 1840 wakeup(&runin); 1841 } 1842 swtch(); 1843 if(issig()) 1844 goto psig; 1845 } else { 1846 spl6(); 1847 rp->p_wchan = chan; 1848 rp->p_stat = SSLEEP; 1849 rp->p_pri = pri; 1850 spl0(); 1851 swtch(); 1852 } 1853 PS->integ = s; 1854 return; 1855 1856 /* 1857 * If priority was low (>=0) and 1858 * there has been a signal, 1859 * execute non-local goto to 1860 * the qsav location. 1861 * (see trap1/trap.c) 1862 */ 1863 psig: 1864 aretu(u.u_qsav); 1865 } 1866 /* ------------------------ */ 1867 1868 /* 1869 * Wake up all processes sleeping on chan. 1870 */ 1871 wakeup(chan) 1872 { 1873 register struct proc *p; 1874 register c, i; 1875 1876 c = chan; 1877 p = &proc[0]; 1878 i = NPROC; 1879 do { 1880 if(p->p_wchan == c) { 1881 setrun(p); 1882 } 1883 p++; 1884 } while(--i); 1885 } 1886 /* ------------------------ */ 1887 1888 /* 1889 * Set the process running; 1890 * arrange for it to be swapped in if necessary. 1891 */ 1892 setrun(p) 1893 { 1894 register struct proc *rp; 1895 1896 rp = p; 1897 rp->p_wchan = 0; 1898 rp->p_stat = SRUN; 1899 if(rp->p_pri < curpri) 1900 runrun++; 1901 if(runout != 0 && (rp->p_flag&SLOAD) == 0) { 1902 runout = 0; 1903 wakeup(&runout); 1904 } 1905 } 1906 /* ------------------------ */ 1907 1908 /* 1909 * Set user priority. 1910 * The rescheduling flag (runrun) 1911 * is set if the priority is higher 1912 * than the currently running process. 1913 */ 1914 setpri(up) 1915 { 1916 register *pp, p; 1917 1918 pp = up; 1919 p = (pp->p_cpu & 0377)/16; 1920 p =+ PUSER + pp->p_nice; 1921 if(p > 127) 1922 p = 127; 1923 if(p > curpri) 1924 runrun++; 1925 pp->p_pri = p; 1926 } 1927 /* ------------------------ */ 1928 1929 /* 1930 * The main loop of the scheduling (swapping) 1931 * process. 1932 * The basic idea is: 1933 * see if anyone wants to be swapped in; 1934 * swap out processes until there is room; 1935 * swap him in; 1936 * repeat. 1937 * Although it is not remarkably evident, the basic 1938 * synchronization here is on the runin flag, which is 1939 * slept on and is set once per second by the clock routine. 1940 * Core shuffling therefore takes place once per second. 1941 * 1942 * panic: swap error -- IO error while swapping. 1943 * this is the one panic that should be 1944 * handled in a less drastic way. Its 1945 * very hard. 1946 */ 1947 sched() 1948 { 1949 struct proc *p1; 1950 register struct proc *rp; 1951 register a, n; 1952 1953 /* 1954 * find user to swap in 1955 * of users ready, select one out longest 1956 */ 1957 1958 goto loop; 1959 1960 sloop: 1961 runin++; 1962 sleep(&runin, PSWP); 1963 1964 loop: 1965 spl6(); 1966 n = -1; 1967 for(rp = &proc[0]; rp < &proc[NPROC]; rp++) 1968 if(rp->p_stat==SRUN && (rp->p_flag&SLOAD)==0 && 1969 rp->p_time > n) { 1970 p1 = rp; 1971 n = rp->p_time; 1972 } 1973 if(n == -1) { 1974 runout++; 1975 sleep(&runout, PSWP); 1976 goto loop; 1977 } 1978 1979 /* 1980 * see if there is core for that process 1981 */ 1982 1983 spl0(); 1984 rp = p1; 1985 a = rp->p_size; 1986 if((rp=rp->p_textp) != NULL) 1987 if(rp->x_ccount == 0) 1988 a =+ rp->x_size; 1989 if((a=malloc(coremap, a)) != NULL) 1990 goto found2; 1991 1992 /* 1993 * none found, 1994 * look around for easy core 1995 */ 1996 1997 spl6(); 1998 for(rp = &proc[0]; rp < &proc[NPROC]; rp++) 1999 if((rp->p_flag&(SSYS|SLOCK|SLOAD))==SLOAD && 2000 (rp->p_stat == SWAIT || rp->p_stat==SSTOP)) 2001 goto found1; 2002 2003 /* 2004 * no easy core, 2005 * if this process is deserving, 2006 * look around for 2007 * oldest process in core 2008 */ 2009 2010 if(n < 3) 2011 goto sloop; 2012 n = -1; 2013 for(rp = &proc[0]; rp < &proc[NPROC]; rp++) 2014 if((rp->p_flag&(SSYS|SLOCK|SLOAD))==SLOAD && 2015 (rp->p_stat==SRUN || rp->p_stat==SSLEEP) && 2016 rp->p_time > n) { 2017 p1 = rp; 2018 n = rp->p_time; 2019 } 2020 if(n < 2) 2021 goto sloop; 2022 rp = p1; 2023 2024 /* 2025 * swap user out 2026 */ 2027 2028 found1: 2029 spl0(); 2030 rp->p_flag =& ~SLOAD; 2031 xswap(rp, 1, 0); 2032 goto loop; 2033 2034 /* 2035 * swap user in 2036 */ 2037 2038 found2: 2039 if((rp=p1->p_textp) != NULL) { 2040 if(rp->x_ccount == 0) { 2041 if(swap(rp->x_daddr, a, rp->x_size, B_READ)) 2042 goto swaper; 2043 rp->x_caddr = a; 2044 a =+ rp->x_size; 2045 } 2046 rp->x_ccount++; 2047 } 2048 rp = p1; 2049 if(swap(rp->p_addr, a, rp->p_size, B_READ)) 2050 goto swaper; 2051 mfree(swapmap, (rp->p_size+7)/8, rp->p_addr); 2052 rp->p_addr = a; 2053 rp->p_flag =| SLOAD; 2054 rp->p_time = 0; 2055 goto loop; 2056 2057 swaper: 2058 panic("swap error"); 2059 } 2060 /* ------------------------ */ 2061 2062 /* 2063 * This routine is called to reschedule the CPU. 2064 * if the calling process is not in RUN state, 2065 * arrangements for it to restart must have 2066 * been made elsewhere, usually by calling via sleep. 2067 */ 2068 swtch() 2069 { 2070 static struct proc *p; 2071 register i, n; 2072 register struct proc *rp; 2073 2074 if(p == NULL) 2075 p = &proc[0]; 2076 /* 2077 * Remember stack of caller 2078 */ 2079 savu(u.u_rsav); 2080 /* 2081 * Switch to scheduler's stack 2082 */ 2083 retu(proc[0].p_addr); 2084 2085 loop: 2086 runrun = 0; 2087 rp = p; 2088 p = NULL; 2089 n = 128; 2090 /* 2091 * Search for highest-priority runnable process 2092 */ 2093 i = NPROC; 2094 do { 2095 rp++; 2096 if(rp >= &proc[NPROC]) 2097 rp = &proc[0]; 2098 if(rp->p_stat==SRUN && (rp->p_flag&SLOAD)!=0) { 2099 if(rp->p_pri < n) { 2100 p = rp; 2101 n = rp->p_pri; 2102 } 2103 } 2104 } while(--i); 2105 /* 2106 * If no process is runnable, idle. 2107 */ 2108 if(p == NULL) { 2109 p = rp; 2110 idle(); 2111 goto loop; 2112 } 2113 rp = p; 2114 curpri = n; 2115 /* 2116 * Switch to stack of the new process and set up 2117 * his segmentation registers. 2118 */ 2119 retu(rp->p_addr); 2120 sureg(); 2121 /* 2122 * If the new process paused because it was 2123 * swapped out, set the stack level to the last call 2124 * to savu(u_ssav). This means that the return 2125 * which is executed immediately after the call to aretu 2126 * actually returns from the last routine which did 2127 * the savu. 2128 * 2129 * You are not expected to understand this. 2130 */ 2131 if(rp->p_flag&SSWAP) { 2132 rp->p_flag =& ~SSWAP; 2133 aretu(u.u_ssav); 2134 } 2135 /* 2136 * The value returned here has many subtle implications. 2137 * See the newproc comments. 2138 */ 2139 return(1); 2140 } 2141 /* ------------------------ */ 2142 2143 /* 2144 * Create a new process-- the internal version of 2145 * sys fork. 2146 * It returns 1 in the new process. 2147 * How this happens is rather hard to understand. 2148 * The essential fact is that the new process is created 2149 * in such a way that appears to have started executing 2150 * in the same call to newproc as the parent; 2151 * but in fact the code that runs is that of swtch. 2152 * The subtle implication of the returned value of swtch 2153 * (see above) is that this is the value that newproc's 2154 * caller in the new process sees. 2155 */ 2156 newproc() 2157 { 2158 int a1, a2; 2159 struct proc *p, *up; 2160 register struct proc *rpp; 2161 register *rip, n; 2162 2163 p = NULL; 2164 /* 2165 * First, just locate a slot for a process 2166 * and copy the useful info from this process into it. 2167 * The panic "cannot happen" because fork has already 2168 * checked for the existence of a slot. 2169 */ 2170 retry: 2171 mpid++; 2172 if(mpid < 0) { 2173 mpid = 0; 2174 goto retry; 2175 } 2176 for(rpp = &proc[0]; rpp < &proc[NPROC]; rpp++) { 2177 if(rpp->p_stat == NULL && p==NULL) 2178 p = rpp; 2179 if (rpp->p_pid==mpid) 2180 goto retry; 2181 } 2182 if ((rpp = p)==NULL) 2183 panic("no procs"); 2184 2185 /* 2186 * make proc entry for new proc 2187 */ 2188 2189 rip = u.u_procp; 2190 up = rip; 2191 rpp->p_stat = SRUN; 2192 rpp->p_flag = SLOAD; 2193 rpp->p_uid = rip->p_uid; 2194 rpp->p_ttyp = rip->p_ttyp; 2195 rpp->p_nice = rip->p_nice; 2196 rpp->p_textp = rip->p_textp; 2197 rpp->p_pid = mpid; 2198 rpp->p_ppid = rip->p_pid; 2199 rpp->p_time = 0; 2200 2201 /* 2202 * make duplicate entries 2203 * where needed 2204 */ 2205 2206 for(rip = &u.u_ofile[0]; rip < &u.u_ofile[NOFILE];) 2207 if((rpp = *rip++) != NULL) 2208 rpp->f_count++; 2209 if((rpp=up->p_textp) != NULL) { 2210 rpp->x_count++; 2211 rpp->x_ccount++; 2212 } 2213 u.u_cdir->i_count++; 2214 /* 2215 * Partially simulate the environment 2216 * of the new process so that when it is actually 2217 * created (by copying) it will look right. 2218 */ 2219 savu(u.u_rsav); 2220 rpp = p; 2221 u.u_procp = rpp; 2222 rip = up; 2223 n = rip->p_size; 2224 a1 = rip->p_addr; 2225 rpp->p_size = n; 2226 a2 = malloc(coremap, n); 2227 /* 2228 * If there is not enough core for the 2229 * new process, swap out the current process to generate the 2230 * copy. 2231 */ 2232 if(a2 == NULL) { 2233 rip->p_stat = SIDL; 2234 rpp->p_addr = a1; 2235 savu(u.u_ssav); 2236 xswap(rpp, 0, 0); 2237 rpp->p_flag =| SSWAP; 2238 rip->p_stat = SRUN; 2239 } else { 2240 /* 2241 * There is core, so just copy. 2242 */ 2243 rpp->p_addr = a2; 2244 while(n--) 2245 copyseg(a1++, a2++); 2246 } 2247 u.u_procp = rip; 2248 return(0); 2249 } 2250 /* ------------------------ */ 2251 2252 /* 2253 * Change the size of the data+stack regions of the process. 2254 * If the size is shrinking, it's easy-- just release the extra core. 2255 * If it's growing, and there is core, just allocate it 2256 * and copy the image, taking care to reset registers to account 2257 * for the fact that the system's stack has moved. 2258 * If there is no core, arrange for the process to be swapped 2259 * out after adjusting the size requirement-- when it comes 2260 * in, enough core will be allocated. 2261 * Because of the ssave and SSWAP flags, control will 2262 * resume after the swap in swtch, which executes the return 2263 * from this stack level. 2264 * 2265 * After the expansion, the caller will take care of copying 2266 * the user's stack towards or away from the data area. 2267 */ 2268 expand(newsize) 2269 { 2270 int i, n; 2271 register *p, a1, a2; 2272 2273 p = u.u_procp; 2274 n = p->p_size; 2275 p->p_size = newsize; 2276 a1 = p->p_addr; 2277 if(n >= newsize) { 2278 mfree(coremap, n-newsize, a1+newsize); 2279 return; 2280 } 2281 savu(u.u_rsav); 2282 a2 = malloc(coremap, newsize); 2283 if(a2 == NULL) { 2284 savu(u.u_ssav); 2285 xswap(p, 1, n); 2286 p->p_flag =| SSWAP; 2287 swtch(); 2288 /* no return */ 2289 } 2290 p->p_addr = a2; 2291 for(i=0; i2292 copyseg(a1+i, a2++); 2293 mfree(coremap, n, a1); 2294 retu(p->p_addr); 2295 sureg(); 2296 } 2297 /* ------------------------ */ 2298 2299