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: /* --------------------------- */