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