BOOK.TXT
资源名称:os_source.zip [点击查看]
上传用户:datang2001
上传日期:2007-02-01
资源大小:53269k
文件大小:999k
源码类别:
操作系统开发
开发平台:
C/C++
- 13915 vid_vid_copy(cons->c_start + scr_width, cons->c_start, chars);
- 13916 } else
- 13917 if (!wrap && cons->c_org + scr_size + scr_width >= cons->c_limit) {
- 13918 vid_vid_copy(cons->c_org + scr_width, cons->c_start, chars);
- 13919 cons->c_org = cons->c_start;
- 13920 } else {
- 13921 cons->c_org = (cons->c_org + scr_width) & vid_mask;
- 13922 }
- 13923 new_line = (cons->c_org + chars) & vid_mask;
- 13924 } else {
- 13925 /* Scroll one line down in 3 ways: soft, avoid wrap, use origin. */
- 13926 if (softscroll) {
- 13927 vid_vid_copy(cons->c_start, cons->c_start + scr_width, chars);
- 13928 } else
- 13929 if (!wrap && cons->c_org < cons->c_start + scr_width) {
- 13930 new_org = cons->c_limit - scr_size;
- 13931 vid_vid_copy(cons->c_org, new_org + scr_width, chars);
- 13932 cons->c_org = new_org;
- 13933 } else {
- 13934 cons->c_org = (cons->c_org - scr_width) & vid_mask;
- 13935 }
- 13936 new_line = cons->c_org;
- 13937 }
- 13938 /* Blank the new line at top or bottom. */
- 13939 blank_color = cons->c_blank;
- 13940 mem_vid_copy(BLANK_MEM, new_line, scr_width);
- 13941
- 13942 /* Set the new video origin. */
- 13943 if (cons == curcons) set_6845(VID_ORG, cons->c_org);
- 13944 flush(cons);
- 13945 }
- 13948 /*===========================================================================*
- 13949 * flush *
- 13950 *===========================================================================*/
- 13951 PRIVATE void flush(cons)
- 13952 register console_t *cons; /* pointer to console struct */
- 13953 {
- 13954 /* Send characters buffered in 'ramqueue' to screen memory, check the new
- 13955 * cursor position, compute the new hardware cursor position and set it.
- 13956 */
- 13957 unsigned cur;
- 13958 tty_t *tp = cons->c_tty;
- 13959
- 13960 /* Have the characters in 'ramqueue' transferred to the screen. */
- 13961 if (cons->c_rwords > 0) {
- 13962 mem_vid_copy(cons->c_ramqueue, cons->c_cur, cons->c_rwords);
- 13963 cons->c_rwords = 0;
- 13964
- 13965 /* TTY likes to know the current column and if echoing messed up. */
- 13966 tp->tty_position = cons->c_column;
- 13967 tp->tty_reprint = TRUE;
- 13968 }
- 13969
- 13970 /* Check and update the cursor position. */
- 13971 if (cons->c_column < 0) cons->c_column = 0;
- 13972 if (cons->c_column > scr_width) cons->c_column = scr_width;
- 13973 if (cons->c_row < 0) cons->c_row = 0;
- 13974 if (cons->c_row >= scr_lines) cons->c_row = scr_lines - 1;
- 13975 cur = cons->c_org + cons->c_row * scr_width + cons->c_column;
- 13976 if (cur != cons->c_cur) {
- 13977 if (cons == curcons) set_6845(CURSOR, cur);
- 13978 cons->c_cur = cur;
- 13979 }
- 13980 }
- 13983 /*===========================================================================*
- 13984 * parse_escape *
- 13985 *===========================================================================*/
- 13986 PRIVATE void parse_escape(cons, c)
- 13987 register console_t *cons; /* pointer to console struct */
- 13988 char c; /* next character in escape sequence */
- 13989 {
- 13990 /* The following ANSI escape sequences are currently supported.
- 13991 * If n and/or m are omitted, they default to 1. Omitted s defaults to 0.
- 13992 * ESC [nA moves up n lines
- 13993 * ESC [nB moves down n lines
- 13994 * ESC [nC moves right n spaces
- 13995 * ESC [nD moves left n spaces
- 13996 * ESC [m;nH moves cursor to (m,n)
- 13997 * ESC [sJ clears screen relative to cursor (0 to end, 1 from start, 2 all)
- 13998 * ESC [sK clears line relative to cursor (0 to end, 1 from start, 2 all)
- 13999 * ESC [nL inserts n lines at cursor
- 14000 * ESC [nM deletes n lines at cursor
- 14001 * ESC [nP deletes n chars at cursor
- 14002 * ESC [n@ inserts n chars at cursor
- 14003 * ESC [nm enables rendition n (0= normal, 1=bold, 4=underline, 5=blinking,
- 14004 * 7=reverse, 30..37 set foreground color, 40..47 set background color)
- 14005 * ESC M scrolls the screen backwards if the cursor is on the top line
- 14006 */
- 14007
- 14008 switch (cons->c_esc_state) {
- 14009 case 1: /* ESC seen */
- 14010 cons->c_esc_intro = ' ';
- 14011 cons->c_esc_parmp = cons->c_esc_parmv;
- 14012 cons->c_esc_parmv[0] = cons->c_esc_parmv[1] = 0;
- 14013 switch (c) {
- 14014 case '[': /* Control Sequence Introducer */
- 14015 cons->c_esc_intro = c;
- 14016 cons->c_esc_state = 2;
- 14017 break;
- 14018 case 'M': /* Reverse Index */
- 14019 do_escape(cons, c);
- 14020 break;
- 14021 default:
- 14022 cons->c_esc_state = 0;
- 14023 }
- 14024 break;
- 14025
- 14026 case 2: /* ESC [ seen */
- 14027 if (c >= '0' && c <= '9') {
- 14028 if (cons->c_esc_parmp < bufend(cons->c_esc_parmv))
- 14029 *cons->c_esc_parmp = *cons->c_esc_parmp * 10 + (c-'0');
- 14030 } else
- 14031 if (c == ';') {
- 14032 if (++cons->c_esc_parmp < bufend(cons->c_esc_parmv))
- 14033 *cons->c_esc_parmp = 0;
- 14034 } else {
- 14035 do_escape(cons, c);
- 14036 }
- 14037 break;
- 14038 }
- 14039 }
- 14042 /*===========================================================================*
- 14043 * do_escape *
- 14044 *===========================================================================*/
- 14045 PRIVATE void do_escape(cons, c)
- 14046 register console_t *cons; /* pointer to console struct */
- 14047 char c; /* next character in escape sequence */
- 14048 {
- 14049 int value, n;
- 14050 unsigned src, dst, count;
- 14051
- 14052 /* Some of these things hack on screen RAM, so it had better be up to date */
- 14053 flush(cons);
- 14054
- 14055 if (cons->c_esc_intro == ' ') {
- 14056 /* Handle a sequence beginning with just ESC */
- 14057 switch (c) {
- 14058 case 'M': /* Reverse Index */
- 14059 if (cons->c_row == 0) {
- 14060 scroll_screen(cons, SCROLL_DOWN);
- 14061 } else {
- 14062 cons->c_row--;
- 14063 }
- 14064 flush(cons);
- 14065 break;
- 14066
- 14067 default: break;
- 14068 }
- 14069 } else
- 14070 if (cons->c_esc_intro == '[') {
- 14071 /* Handle a sequence beginning with ESC [ and parameters */
- 14072 value = cons->c_esc_parmv[0];
- 14073 switch (c) {
- 14074 case 'A': /* ESC [nA moves up n lines */
- 14075 n = (value == 0 ? 1 : value);
- 14076 cons->c_row -= n;
- 14077 flush(cons);
- 14078 break;
- 14079
- 14080 case 'B': /* ESC [nB moves down n lines */
- 14081 n = (value == 0 ? 1 : value);
- 14082 cons->c_row += n;
- 14083 flush(cons);
- 14084 break;
- 14085
- 14086 case 'C': /* ESC [nC moves right n spaces */
- 14087 n = (value == 0 ? 1 : value);
- 14088 cons->c_column += n;
- 14089 flush(cons);
- 14090 break;
- 14091
- 14092 case 'D': /* ESC [nD moves left n spaces */
- 14093 n = (value == 0 ? 1 : value);
- 14094 cons->c_column -= n;
- 14095 flush(cons);
- 14096 break;
- 14097
- 14098 case 'H': /* ESC [m;nH" moves cursor to (m,n) */
- 14099 cons->c_row = cons->c_esc_parmv[0] - 1;
- 14100 cons->c_column = cons->c_esc_parmv[1] - 1;
- 14101 flush(cons);
- 14102 break;
- 14103
- 14104 case 'J': /* ESC [sJ clears in display */
- 14105 switch (value) {
- 14106 case 0: /* Clear from cursor to end of screen */
- 14107 count = scr_size - (cons->c_cur - cons->c_org);
- 14108 dst = cons->c_cur;
- 14109 break;
- 14110 case 1: /* Clear from start of screen to cursor */
- 14111 count = cons->c_cur - cons->c_org;
- 14112 dst = cons->c_org;
- 14113 break;
- 14114 case 2: /* Clear entire screen */
- 14115 count = scr_size;
- 14116 dst = cons->c_org;
- 14117 break;
- 14118 default: /* Do nothing */
- 14119 count = 0;
- 14120 dst = cons->c_org;
- 14121 }
- 14122 blank_color = cons->c_blank;
- 14123 mem_vid_copy(BLANK_MEM, dst, count);
- 14124 break;
- 14125
- 14126 case 'K': /* ESC [sK clears line from cursor */
- 14127 switch (value) {
- 14128 case 0: /* Clear from cursor to end of line */
- 14129 count = scr_width - cons->c_column;
- 14130 dst = cons->c_cur;
- 14131 break;
- 14132 case 1: /* Clear from beginning of line to cursor */
- 14133 count = cons->c_column;
- 14134 dst = cons->c_cur - cons->c_column;
- 14135 break;
- 14136 case 2: /* Clear entire line */
- 14137 count = scr_width;
- 14138 dst = cons->c_cur - cons->c_column;
- 14139 break;
- 14140 default: /* Do nothing */
- 14141 count = 0;
- 14142 dst = cons->c_cur;
- 14143 }
- 14144 blank_color = cons->c_blank;
- 14145 mem_vid_copy(BLANK_MEM, dst, count);
- 14146 break;
- 14147
- 14148 case 'L': /* ESC [nL inserts n lines at cursor */
- 14149 n = value;
- 14150 if (n < 1) n = 1;
- 14151 if (n > (scr_lines - cons->c_row))
- 14152 n = scr_lines - cons->c_row;
- 14153
- 14154 src = cons->c_org + cons->c_row * scr_width;
- 14155 dst = src + n * scr_width;
- 14156 count = (scr_lines - cons->c_row - n) * scr_width;
- 14157 vid_vid_copy(src, dst, count);
- 14158 blank_color = cons->c_blank;
- 14159 mem_vid_copy(BLANK_MEM, src, n * scr_width);
- 14160 break;
- 14161
- 14162 case 'M': /* ESC [nM deletes n lines at cursor */
- 14163 n = value;
- 14164 if (n < 1) n = 1;
- 14165 if (n > (scr_lines - cons->c_row))
- 14166 n = scr_lines - cons->c_row;
- 14167
- 14168 dst = cons->c_org + cons->c_row * scr_width;
- 14169 src = dst + n * scr_width;
- 14170 count = (scr_lines - cons->c_row - n) * scr_width;
- 14171 vid_vid_copy(src, dst, count);
- 14172 blank_color = cons->c_blank;
- 14173 mem_vid_copy(BLANK_MEM, dst + count, n * scr_width);
- 14174 break;
- 14175
- 14176 case '@': /* ESC [n@ inserts n chars at cursor */
- 14177 n = value;
- 14178 if (n < 1) n = 1;
- 14179 if (n > (scr_width - cons->c_column))
- 14180 n = scr_width - cons->c_column;
- 14181
- 14182 src = cons->c_cur;
- 14183 dst = src + n;
- 14184 count = scr_width - cons->c_column - n;
- 14185 vid_vid_copy(src, dst, count);
- 14186 blank_color = cons->c_blank;
- 14187 mem_vid_copy(BLANK_MEM, src, n);
- 14188 break;
- 14189
- 14190 case 'P': /* ESC [nP deletes n chars at cursor */
- 14191 n = value;
- 14192 if (n < 1) n = 1;
- 14193 if (n > (scr_width - cons->c_column))
- 14194 n = scr_width - cons->c_column;
- 14195
- 14196 dst = cons->c_cur;
- 14197 src = dst + n;
- 14198 count = scr_width - cons->c_column - n;
- 14199 vid_vid_copy(src, dst, count);
- 14200 blank_color = cons->c_blank;
- 14201 mem_vid_copy(BLANK_MEM, dst + count, n);
- 14202 break;
- 14203
- 14204 case 'm': /* ESC [nm enables rendition n */
- 14205 switch (value) {
- 14206 case 1: /* BOLD */
- 14207 if (color) {
- 14208 /* Can't do bold, so use yellow */
- 14209 cons->c_attr = (cons->c_attr & 0xf0ff) | 0x0E00;
- 14210 } else {
- 14211 /* Set intensity bit */
- 14212 cons->c_attr |= 0x0800;
- 14213 }
- 14214 break;
- 14215
- 14216 case 4: /* UNDERLINE */
- 14217 if (color) {
- 14218 /* Use light green */
- 14219 cons->c_attr = (cons->c_attr & 0xf0ff) | 0x0A00;
- 14220 } else {
- 14221 cons->c_attr = (cons->c_attr & 0x8900);
- 14222 }
- 14223 break;
- 14224
- 14225 case 5: /* BLINKING */
- 14226 if (color) {
- 14227 /* Use magenta */
- 14228 cons->c_attr = (cons->c_attr & 0xf0ff) | 0x0500;
- 14229 } else {
- 14230 /* Set the blink bit */
- 14231 cons->c_attr |= 0x8000;
- 14232 }
- 14233 break;
- 14234
- 14235 case 7: /* REVERSE */
- 14236 if (color) {
- 14237 /* Swap fg and bg colors */
- 14238 cons->c_attr =
- 14239 ((cons->c_attr & 0xf000) >> 4) |
- 14240 ((cons->c_attr & 0x0f00) << 4);
- 14241 } else
- 14242 if ((cons->c_attr & 0x7000) == 0) {
- 14243 cons->c_attr = (cons->c_attr & 0x8800) | 0x7000;
- 14244 } else {
- 14245 cons->c_attr = (cons->c_attr & 0x8800) | 0x0700;
- 14246 }
- 14247 break;
- 14248
- 14249 default: /* COLOR */
- 14250 if (30 <= value && value <= 37) {
- 14251 cons->c_attr =
- 14252 (cons->c_attr & 0xf0ff) |
- 14253 (ansi_colors[(value - 30)] << 8);
- 14254 cons->c_blank =
- 14255 (cons->c_blank & 0xf0ff) |
- 14256 (ansi_colors[(value - 30)] << 8);
- 14257 } else
- 14258 if (40 <= value && value <= 47) {
- 14259 cons->c_attr =
- 14260 (cons->c_attr & 0x0fff) |
- 14261 (ansi_colors[(value - 40)] << 12);
- 14262 cons->c_blank =
- 14263 (cons->c_blank & 0x0fff) |
- 14264 (ansi_colors[(value - 40)] << 12);
- 14265 } else {
- 14266 cons->c_attr = cons->c_blank;
- 14267 }
- 14268 break;
- 14269 }
- 14270 break;
- 14271 }
- 14272 }
- 14273 cons->c_esc_state = 0;
- 14274 }
- 14277 /*===========================================================================*
- 14278 * set_6845 *
- 14279 *===========================================================================*/
- 14280 PRIVATE void set_6845(reg, val)
- 14281 int reg; /* which register pair to set */
- 14282 unsigned val; /* 16-bit value to set it to */
- 14283 {
- 14284 /* Set a register pair inside the 6845.
- 14285 * Registers 12-13 tell the 6845 where in video ram to start
- 14286 * Registers 14-15 tell the 6845 where to put the cursor
- 14287 */
- 14288 lock(); /* try to stop h/w loading in-between value */
- 14289 out_byte(vid_port + INDEX, reg); /* set the index register */
- 14290 out_byte(vid_port + DATA, (val>>8) & BYTE); /* output high byte */
- 14291 out_byte(vid_port + INDEX, reg + 1); /* again */
- 14292 out_byte(vid_port + DATA, val&BYTE); /* output low byte */
- 14293 unlock();
- 14294 }
- 14297 /*===========================================================================*
- 14298 * beep *
- 14299 *===========================================================================*/
- 14300 PRIVATE void beep()
- 14301 {
- 14302 /* Making a beeping sound on the speaker (output for CRTL-G).
- 14303 * This routine works by turning on the bits 0 and 1 in port B of the 8255
- 14304 * chip that drives the speaker.
- 14305 */
- 14306
- 14307 message mess;
- 14308
- 14309 if (beeping) return;
- 14310 out_byte(TIMER_MODE, 0xB6); /* set up timer channel 2 (square wave) */
- 14311 out_byte(TIMER2, BEEP_FREQ & BYTE); /* load low-order bits of frequency */
- 14312 out_byte(TIMER2, (BEEP_FREQ >> 8) & BYTE); /* now high-order bits */
- 14313 lock(); /* guard PORT_B from keyboard intr handler */
- 14314 out_byte(PORT_B, in_byte(PORT_B) | 3); /* turn on beep bits */
- 14315 unlock();
- 14316 beeping = TRUE;
- 14317
- 14318 mess.m_type = SET_ALARM;
- 14319 mess.CLOCK_PROC_NR = TTY;
- 14320 mess.DELTA_TICKS = B_TIME;
- 14321 mess.FUNC_TO_CALL = (sighandler_t) stop_beep;
- 14322 sendrec(CLOCK, &mess);
- 14323 }
- 14326 /*===========================================================================*
- 14327 * stop_beep *
- 14328 *===========================================================================*/
- 14329 PRIVATE void stop_beep()
- 14330 {
- 14331 /* Turn off the beeper by turning off bits 0 and 1 in PORT_B. */
- 14332
- 14333 lock(); /* guard PORT_B from keyboard intr handler */
- 14334 out_byte(PORT_B, in_byte(PORT_B) & ~3);
- 14335 beeping = FALSE;
- 14336 unlock();
- 14337 }
- 14340 /*===========================================================================*
- 14341 * scr_init *
- 14342 *===========================================================================*/
- 14343 PUBLIC void scr_init(tp)
- 14344 tty_t *tp;
- 14345 {
- 14346 /* Initialize the screen driver. */
- 14347 console_t *cons;
- 14348 phys_bytes vid_base;
- 14349 u16_t bios_crtbase;
- 14350 int line;
- 14351 unsigned page_size;
- 14352
- 14353 /* Associate console and TTY. */
- 14354 line = tp - &tty_table[0];
- 14355 if (line >= nr_cons) return;
- 14356 cons = &cons_table[line];
- 14357 cons->c_tty = tp;
- 14358 tp->tty_priv = cons;
- 14359
- 14360 /* Initialize the keyboard driver. */
- 14361 kb_init(tp);
- 14362
- 14363 /* Output functions. */
- 14364 tp->tty_devwrite = cons_write;
- 14365 tp->tty_echo = cons_echo;
- 14366
- 14367 /* Get the BIOS parameters that tells the VDU I/O base register. */
- 14368 phys_copy(0x463L, vir2phys(&bios_crtbase), 2L);
- 14369
- 14370 vid_port = bios_crtbase;
- 14371
- 14372 if (color) {
- 14373 vid_base = COLOR_BASE;
- 14374 vid_size = COLOR_SIZE;
- 14375 } else {
- 14376 vid_base = MONO_BASE;
- 14377 vid_size = MONO_SIZE;
- 14378 }
- 14379 if (ega) vid_size = EGA_SIZE; /* for both EGA and VGA */
- 14380 wrap = !ega;
- 14381
- 14382 vid_seg = protected_mode ? VIDEO_SELECTOR : physb_to_hclick(vid_base);
- 14383 init_dataseg(&gdt[VIDEO_INDEX], vid_base, (phys_bytes) vid_size,
- 14384 TASK_PRIVILEGE);
- 14385 vid_size >>= 1; /* word count */
- 14386 vid_mask = vid_size - 1;
- 14387
- 14388 /* There can be as many consoles as video memory allows. */
- 14389 nr_cons = vid_size / scr_size;
- 14390 if (nr_cons > NR_CONS) nr_cons = NR_CONS;
- 14391 if (nr_cons > 1) wrap = 0;
- 14392 page_size = vid_size / nr_cons;
- 14393 cons->c_start = line * page_size;
- 14394 cons->c_limit = cons->c_start + page_size;
- 14395 cons->c_org = cons->c_start;
- 14396 cons->c_attr = cons->c_blank = BLANK_COLOR;
- 14397
- 14398 /* Clear the screen. */
- 14399 blank_color = BLANK_COLOR;
- 14400 mem_vid_copy(BLANK_MEM, cons->c_start, scr_size);
- 14401 select_console(0);
- 14402 }
- 14405 /*===========================================================================*
- 14406 * putk *
- 14407 *===========================================================================*/
- 14408 PUBLIC void putk(c)
- 14409 int c; /* character to print */
- 14410 {
- 14411 /* This procedure is used by the version of printf() that is linked with
- 14412 * the kernel itself. The one in the library sends a message to FS, which is
- 14413 * not what is needed for printing within the kernel. This version just queues
- 14414 * the character and starts the output.
- 14415 */
- 14416
- 14417 if (c != 0) {
- 14418 if (c == 'n') putk('r');
- 14419 out_char(&cons_table[0], (int) c);
- 14420 } else {
- 14421 flush(&cons_table[0]);
- 14422 }
- 14423 }
- 14426 /*===========================================================================*
- 14427 * toggle_scroll *
- 14428 *===========================================================================*/
- 14429 PUBLIC void toggle_scroll()
- 14430 {
- 14431 /* Toggle between hardware and software scroll. */
- 14432
- 14433 cons_org0();
- 14434 softscroll = !softscroll;
- 14435 printf("%sware scrolling enabled.n", softscroll ? "Soft" : "Hard");
- 14436 }
- 14439 /*===========================================================================*
- 14440 * cons_stop *
- 14441 *===========================================================================*/
- 14442 PUBLIC void cons_stop()
- 14443 {
- 14444 /* Prepare for halt or reboot. */
- 14445
- 14446 cons_org0();
- 14447 softscroll = 1;
- 14448 select_console(0);
- 14449 cons_table[0].c_attr = cons_table[0].c_blank = BLANK_COLOR;
- 14450 }
- 14453 /*===========================================================================*
- 14454 * cons_org0 *
- 14455 *===========================================================================*/
- 14456 PRIVATE void cons_org0()
- 14457 {
- 14458 /* Scroll video memory back to put the origin at 0. */
- 14459
- 14460 int cons_line;
- 14461 console_t *cons;
- 14462 unsigned n;
- 14463
- 14464 for (cons_line = 0; cons_line < nr_cons; cons_line++) {
- 14465 cons = &cons_table[cons_line];
- 14466 while (cons->c_org > cons->c_start) {
- 14467 n = vid_size - scr_size; /* amount of unused memory */
- 14468 if (n > cons->c_org - cons->c_start)
- 14469 n = cons->c_org - cons->c_start;
- 14470 vid_vid_copy(cons->c_org, cons->c_org - n, scr_size);
- 14471 cons->c_org -= n;
- 14472 }
- 14473 flush(cons);
- 14474 }
- 14475 select_console(current);
- 14476 }
- 14479 /*===========================================================================*
- 14480 * select_console *
- 14481 *===========================================================================*/
- 14482 PUBLIC void select_console(int cons_line)
- 14483 {
- 14484 /* Set the current console to console number 'cons_line'. */
- 14485
- 14486 if (cons_line < 0 || cons_line >= nr_cons) return;
- 14487 current = cons_line;
- 14488 curcons = &cons_table[cons_line];
- 14489 set_6845(VID_ORG, curcons->c_org);
- 14490 set_6845(CURSOR, curcons->c_cur);
- 14491 }
- 14494 /*===========================================================================*
- 14495 * con_loadfont *
- 14496 *===========================================================================*/
- 14497 PUBLIC int con_loadfont(user_phys)
- 14498 phys_bytes user_phys;
- 14499 {
- 14500 /* Load a font into the EGA or VGA adapter. */
- 14501
- 14502 static struct sequence seq1[7] = {
- 14503 { GA_SEQUENCER_INDEX, 0x00, 0x01 },
- 14504 { GA_SEQUENCER_INDEX, 0x02, 0x04 },
- 14505 { GA_SEQUENCER_INDEX, 0x04, 0x07 },
- 14506 { GA_SEQUENCER_INDEX, 0x00, 0x03 },
- 14507 { GA_GRAPHICS_INDEX, 0x04, 0x02 },
- 14508 { GA_GRAPHICS_INDEX, 0x05, 0x00 },
- 14509 { GA_GRAPHICS_INDEX, 0x06, 0x00 },
- 14510 };
- 14511 static struct sequence seq2[7] = {
- 14512 { GA_SEQUENCER_INDEX, 0x00, 0x01 },
- 14513 { GA_SEQUENCER_INDEX, 0x02, 0x03 },
- 14514 { GA_SEQUENCER_INDEX, 0x04, 0x03 },
- 14515 { GA_SEQUENCER_INDEX, 0x00, 0x03 },
- 14516 { GA_GRAPHICS_INDEX, 0x04, 0x00 },
- 14517 { GA_GRAPHICS_INDEX, 0x05, 0x10 },
- 14518 { GA_GRAPHICS_INDEX, 0x06, 0 },
- 14519 };
- 14520
- 14521 seq2[6].value= color ? 0x0E : 0x0A;
- 14522
- 14523 if (!ega) return(ENOTTY);
- 14524
- 14525 lock();
- 14526 ga_program(seq1); /* bring font memory into view */
- 14527
- 14528 phys_copy(user_phys, (phys_bytes)GA_VIDEO_ADDRESS, (phys_bytes)GA_FONT_SIZE);
- 14529
- 14530 ga_program(seq2); /* restore */
- 14531 unlock();
- 14532
- 14533 return(OK);
- 14534 }
- 14537 /*===========================================================================*
- 14538 * ga_program *
- 14539 *===========================================================================*/
- 14540 PRIVATE void ga_program(seq)
- 14541 struct sequence *seq;
- 14542 {
- 14543 /* support function for con_loadfont */
- 14544
- 14545 int len= 7;
- 14546 do {
- 14547 out_byte(seq->index, seq->port);
- 14548 out_byte(seq->index+1, seq->value);
- 14549 seq++;
- 14550 } while (--len > 0);
- 14551 }
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- src/kernel/dmp.c
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- 14600 /* This file contains some dumping routines for debugging. */
- 14601
- 14602 #include "kernel.h"
- 14603 #include <minix/com.h>
- 14604 #include "proc.h"
- 14605
- 14606 char *vargv;
- 14607
- 14608 FORWARD _PROTOTYPE(char *proc_name, (int proc_nr));
- 14609
- 14610 /*===========================================================================*
- 14611 * p_dmp *
- 14612 *===========================================================================*/
- 14613 PUBLIC void p_dmp()
- 14614 {
- 14615 /* Proc table dump */
- 14616
- 14617 register struct proc *rp;
- 14618 static struct proc *oldrp = BEG_PROC_ADDR;
- 14619 int n = 0;
- 14620 phys_clicks text, data, size;
- 14621 int proc_nr;
- 14622
- 14623 printf("n--pid --pc- ---sp- flag -user --sys-- -text- -data- -size- -recv- commandn");
- 14624
- 14625 for (rp = oldrp; rp < END_PROC_ADDR; rp++) {
- 14626 proc_nr = proc_number(rp);
- 14627 if (rp->p_flags & P_SLOT_FREE) continue;
- 14628 if (++n > 20) break;
- 14629 text = rp->p_map[T].mem_phys;
- 14630 data = rp->p_map[D].mem_phys;
- 14631 size = rp->p_map[T].mem_len
- 14632 + ((rp->p_map[S].mem_phys + rp->p_map[S].mem_len) - data);
- 14633 printf("%5d %5lx %6lx %2x %7U %7U %5uK %5uK %5uK ",
- 14634 proc_nr < 0 ? proc_nr : rp->p_pid,
- 14635 (unsigned long) rp->p_reg.pc,
- 14636 (unsigned long) rp->p_reg.sp,
- 14637 rp->p_flags,
- 14638 rp->user_time, rp->sys_time,
- 14639 click_to_round_k(text), click_to_round_k(data),
- 14640 click_to_round_k(size));
- 14641 if (rp->p_flags & RECEIVING) {
- 14642 printf("%-7.7s", proc_name(rp->p_getfrom));
- 14643 } else
- 14644 if (rp->p_flags & SENDING) {
- 14645 printf("S:%-5.5s", proc_name(rp->p_sendto));
- 14646 } else
- 14647 if (rp->p_flags == 0) {
- 14648 printf(" ");
- 14649 }
- 14650 printf("%sn", rp->p_name);
- 14651 }
- 14652 if (rp == END_PROC_ADDR) rp = BEG_PROC_ADDR; else printf("--more--r");
- 14653 oldrp = rp;
- 14654 }
- 14657 /*===========================================================================*
- 14658 * map_dmp *
- 14659 *===========================================================================*/
- 14660 PUBLIC void map_dmp()
- 14661 {
- 14662 register struct proc *rp;
- 14663 static struct proc *oldrp = cproc_addr(HARDWARE);
- 14664 int n = 0;
- 14665 phys_clicks size;
- 14666
- 14667 printf("nPROC NAME- -----TEXT----- -----DATA----- ----STACK----- -SIZE-n");
- 14668 for (rp = oldrp; rp < END_PROC_ADDR; rp++) {
- 14669 if (rp->p_flags & P_SLOT_FREE) continue;
- 14670 if (++n > 20) break;
- 14671 size = rp->p_map[T].mem_len
- 14672 + ((rp->p_map[S].mem_phys + rp->p_map[S].mem_len)
- 14673 - rp->p_map[D].mem_phys);
- 14674 printf("%3d %-6.6s %4x %4x %4x %4x %4x %4x %4x %4x %4x %5uKn",
- 14675 proc_number(rp),
- 14676 rp->p_name,
- 14677 rp->p_map[T].mem_vir, rp->p_map[T].mem_phys, rp->p_map[T].mem_len,
- 14678 rp->p_map[D].mem_vir, rp->p_map[D].mem_phys, rp->p_map[D].mem_len,
- 14679 rp->p_map[S].mem_vir, rp->p_map[S].mem_phys, rp->p_map[S].mem_len,
- 14680 click_to_round_k(size));
- 14681 }
- 14682 if (rp == END_PROC_ADDR) rp = cproc_addr(HARDWARE); else printf("--more--r");
- 14683 oldrp = rp;
- 14684 }
- 14687 /*===========================================================================*
- 14688 * proc_name *
- 14689 *===========================================================================*/
- 14690 PRIVATE char *proc_name(proc_nr)
- 14691 int proc_nr;
- 14692 {
- 14693 if (proc_nr == ANY) return "ANY";
- 14694 return proc_addr(proc_nr)->p_name;
- 14695 }
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- src/kernel/system.c
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- 14700 /* This task handles the interface between file system and kernel as well as
- 14701 * between memory manager and kernel. System services are obtained by sending
- 14702 * sys_task() a message specifying what is needed. To make life easier for
- 14703 * MM and FS, a library is provided with routines whose names are of the
- 14704 * form sys_xxx, e.g. sys_xit sends the SYS_XIT message to sys_task. The
- 14705 * message types and parameters are:
- 14706 *
- 14707 * SYS_FORK informs kernel that a process has forked
- 14708 * SYS_NEWMAP allows MM to set up a process memory map
- 14709 * SYS_GETMAP allows MM to get a process' memory map
- 14710 * SYS_EXEC sets program counter and stack pointer after EXEC
- 14711 * SYS_XIT informs kernel that a process has exited
- 14712 * SYS_GETSP caller wants to read out some process' stack pointer
- 14713 * SYS_TIMES caller wants to get accounting times for a process
- 14714 * SYS_ABORT MM or FS cannot go on; abort MINIX
- 14715 * SYS_FRESH start with a fresh process image during EXEC (68000 only)
- 14716 * SYS_SENDSIG send a signal to a process (POSIX style)
- 14717 * SYS_SIGRETURN complete POSIX-style signalling
- 14718 * SYS_KILL cause a signal to be sent via MM
- 14719 * SYS_ENDSIG finish up after SYS_KILL-type signal
- 14720 * SYS_COPY request a block of data to be copied between processes
- 14721 * SYS_VCOPY request a series of data blocks to be copied between procs
- 14722 * SYS_GBOOT copies the boot parameters to a process
- 14723 * SYS_MEM returns the next free chunk of physical memory
- 14724 * SYS_UMAP compute the physical address for a given virtual address
- 14725 * SYS_TRACE request a trace operation
- 14726 *
- 14727 * Message types and parameters:
- 14728 *
- 14729 * m_type PROC1 PROC2 PID MEM_PTR
- 14730 * ------------------------------------------------------
- 14731 * | SYS_FORK | parent | child | pid | |
- 14732 * |------------+---------+---------+---------+---------|
- 14733 * | SYS_NEWMAP | proc nr | | | map ptr |
- 14734 * |------------+---------+---------+---------+---------|
- 14735 * | SYS_EXEC | proc nr | traced | new sp | |
- 14736 * |------------+---------+---------+---------+---------|
- 14737 * | SYS_XIT | parent | exitee | | |
- 14738 * |------------+---------+---------+---------+---------|
- 14739 * | SYS_GETSP | proc nr | | | |
- 14740 * |------------+---------+---------+---------+---------|
- 14741 * | SYS_TIMES | proc nr | | buf ptr | |
- 14742 * |------------+---------+---------+---------+---------|
- 14743 * | SYS_ABORT | | | | |
- 14744 * |------------+---------+---------+---------+---------|
- 14745 * | SYS_FRESH | proc nr | data_cl | | |
- 14746 * |------------+---------+---------+---------+---------|
- 14747 * | SYS_GBOOT | proc nr | | | bootptr |
- 14748 * |------------+---------+---------+---------+---------|
- 14749 * | SYS_GETMAP | proc nr | | | map ptr |
- 14750 * ------------------------------------------------------
- 14751 *
- 14752 * m_type m1_i1 m1_i2 m1_i3 m1_p1
- 14753 * ----------------+---------+---------+---------+--------------
- 14754 * | SYS_VCOPY | src p | dst p | vec siz | vc addr |
- 14755 * |---------------+---------+---------+---------+-------------|
- 14756 * | SYS_SENDSIG | proc nr | | | smp |
- 14757 * |---------------+---------+---------+---------+-------------|
- 14758 * | SYS_SIGRETURN | proc nr | | | scp |
- 14759 * |---------------+---------+---------+---------+-------------|
- 14760 * | SYS_ENDSIG | proc nr | | | |
- 14761 * -------------------------------------------------------------
- 14762 *
- 14763 * m_type m2_i1 m2_i2 m2_l1 m2_l2
- 14764 * ------------------------------------------------------
- 14765 * | SYS_TRACE | proc_nr | request | addr | data |
- 14766 * ------------------------------------------------------
- 14767 *
- 14768 *
- 14769 * m_type m6_i1 m6_i2 m6_i3 m6_f1
- 14770 * ------------------------------------------------------
- 14771 * | SYS_KILL | proc_nr | sig | | |
- 14772 * ------------------------------------------------------
- 14773 *
- 14774 *
- 14775 * m_type m5_c1 m5_i1 m5_l1 m5_c2 m5_i2 m5_l2 m5_l3
- 14776 * --------------------------------------------------------------------------
- 14777 * | SYS_COPY |src seg|src proc|src vir|dst seg|dst proc|dst vir| byte ct |
- 14778 * --------------------------------------------------------------------------
- 14779 * | SYS_UMAP | seg |proc nr |vir adr| | | | byte ct |
- 14780 * --------------------------------------------------------------------------
- 14781 *
- 14782 *
- 14783 * m_type m1_i1 m1_i2 m1_i3
- 14784 * |------------+----------+----------+----------
- 14785 * | SYS_MEM | mem base | mem size | tot mem |
- 14786 * ----------------------------------------------
- 14787 *
- 14788 * In addition to the main sys_task() entry point, there are 5 other minor
- 14789 * entry points:
- 14790 * cause_sig: take action to cause a signal to occur, sooner or later
- 14791 * inform: tell MM about pending signals
- 14792 * numap: umap D segment starting from process number instead of pointer
- 14793 * umap: compute the physical address for a given virtual address
- 14794 * alloc_segments: allocate segments for 8088 or higher processor
- 14795 */
- 14796
- 14797 #include "kernel.h"
- 14798 #include <signal.h>
- 14799 #include <unistd.h>
- 14800 #include <sys/sigcontext.h>
- 14801 #include <sys/ptrace.h>
- 14802 #include <minix/boot.h>
- 14803 #include <minix/callnr.h>
- 14804 #include <minix/com.h>
- 14805 #include "proc.h"
- 14806 #include "protect.h"
- 14807
- 14808 /* PSW masks. */
- 14809 #define IF_MASK 0x00000200
- 14810 #define IOPL_MASK 0x003000
- 14811
- 14812 PRIVATE message m;
- 14813
- 14814 FORWARD _PROTOTYPE( int do_abort, (message *m_ptr) );
- 14815 FORWARD _PROTOTYPE( int do_copy, (message *m_ptr) );
- 14816 FORWARD _PROTOTYPE( int do_exec, (message *m_ptr) );
- 14817 FORWARD _PROTOTYPE( int do_fork, (message *m_ptr) );
- 14818 FORWARD _PROTOTYPE( int do_gboot, (message *m_ptr) );
- 14819 FORWARD _PROTOTYPE( int do_getsp, (message *m_ptr) );
- 14820 FORWARD _PROTOTYPE( int do_kill, (message *m_ptr) );
- 14821 FORWARD _PROTOTYPE( int do_mem, (message *m_ptr) );
- 14822 FORWARD _PROTOTYPE( int do_newmap, (message *m_ptr) );
- 14823 FORWARD _PROTOTYPE( int do_sendsig, (message *m_ptr) );
- 14824 FORWARD _PROTOTYPE( int do_sigreturn, (message *m_ptr) );
- 14825 FORWARD _PROTOTYPE( int do_endsig, (message *m_ptr) );
- 14826 FORWARD _PROTOTYPE( int do_times, (message *m_ptr) );
- 14827 FORWARD _PROTOTYPE( int do_trace, (message *m_ptr) );
- 14828 FORWARD _PROTOTYPE( int do_umap, (message *m_ptr) );
- 14829 FORWARD _PROTOTYPE( int do_xit, (message *m_ptr) );
- 14830 FORWARD _PROTOTYPE( int do_vcopy, (message *m_ptr) );
- 14831 FORWARD _PROTOTYPE( int do_getmap, (message *m_ptr) );
- 14832
- 14833
- 14834 /*===========================================================================*
- 14835 * sys_task *
- 14836 *===========================================================================*/
- 14837 PUBLIC void sys_task()
- 14838 {
- 14839 /* Main entry point of sys_task. Get the message and dispatch on type. */
- 14840
- 14841 register int r;
- 14842
- 14843 while (TRUE) {
- 14844 receive(ANY, &m);
- 14845
- 14846 switch (m.m_type) { /* which system call */
- 14847 case SYS_FORK: r = do_fork(&m); break;
- 14848 case SYS_NEWMAP: r = do_newmap(&m); break;
- 14849 case SYS_GETMAP: r = do_getmap(&m); break;
- 14850 case SYS_EXEC: r = do_exec(&m); break;
- 14851 case SYS_XIT: r = do_xit(&m); break;
- 14852 case SYS_GETSP: r = do_getsp(&m); break;
- 14853 case SYS_TIMES: r = do_times(&m); break;
- 14854 case SYS_ABORT: r = do_abort(&m); break;
- 14855 case SYS_SENDSIG: r = do_sendsig(&m); break;
- 14856 case SYS_SIGRETURN: r = do_sigreturn(&m); break;
- 14857 case SYS_KILL: r = do_kill(&m); break;
- 14858 case SYS_ENDSIG: r = do_endsig(&m); break;
- 14859 case SYS_COPY: r = do_copy(&m); break;
- 14860 case SYS_VCOPY: r = do_vcopy(&m); break;
- 14861 case SYS_GBOOT: r = do_gboot(&m); break;
- 14862 case SYS_MEM: r = do_mem(&m); break;
- 14863 case SYS_UMAP: r = do_umap(&m); break;
- 14864 case SYS_TRACE: r = do_trace(&m); break;
- 14865 default: r = E_BAD_FCN;
- 14866 }
- 14867
- 14868 m.m_type = r; /* 'r' reports status of call */
- 14869 send(m.m_source, &m); /* send reply to caller */
- 14870 }
- 14871 }
- 14874 /*===========================================================================*
- 14875 * do_fork *
- 14876 *===========================================================================*/
- 14877 PRIVATE int do_fork(m_ptr)
- 14878 register message *m_ptr; /* pointer to request message */
- 14879 {
- 14880 /* Handle sys_fork(). m_ptr->PROC1 has forked. The child is m_ptr->PROC2. */
- 14881
- 14882 reg_t old_ldt_sel;
- 14883 register struct proc *rpc;
- 14884 struct proc *rpp;
- 14885
- 14886 if (!isoksusern(m_ptr->PROC1) || !isoksusern(m_ptr->PROC2))
- 14887 return(E_BAD_PROC);
- 14888 rpp = proc_addr(m_ptr->PROC1);
- 14889 rpc = proc_addr(m_ptr->PROC2);
- 14890
- 14891 /* Copy parent 'proc' struct to child. */
- 14892 old_ldt_sel = rpc->p_ldt_sel; /* stop this being obliterated by copy */
- 14893
- 14894 *rpc = *rpp; /* copy 'proc' struct */
- 14895
- 14896 rpc->p_ldt_sel = old_ldt_sel;
- 14897 rpc->p_nr = m_ptr->PROC2; /* this was obliterated by copy */
- 14898
- 14899 rpc->p_flags |= NO_MAP; /* inhibit the process from running */
- 14900
- 14901 rpc->p_flags &= ~(PENDING | SIG_PENDING | P_STOP);
- 14902
- 14903 /* Only 1 in group should have PENDING, child does not inherit trace status*/
- 14904 sigemptyset(&rpc->p_pending);
- 14905 rpc->p_pendcount = 0;
- 14906 rpc->p_pid = m_ptr->PID; /* install child's pid */
- 14907 rpc->p_reg.retreg = 0; /* child sees pid = 0 to know it is child */
- 14908
- 14909 rpc->user_time = 0; /* set all the accounting times to 0 */
- 14910 rpc->sys_time = 0;
- 14911 rpc->child_utime = 0;
- 14912 rpc->child_stime = 0;
- 14913
- 14914 return(OK);
- 14915 }
- 14918 /*===========================================================================*
- 14919 * do_newmap *
- 14920 *===========================================================================*/
- 14921 PRIVATE int do_newmap(m_ptr)
- 14922 message *m_ptr; /* pointer to request message */
- 14923 {
- 14924 /* Handle sys_newmap(). Fetch the memory map from MM. */
- 14925
- 14926 register struct proc *rp;
- 14927 phys_bytes src_phys;
- 14928 int caller; /* whose space has the new map (usually MM) */
- 14929 int k; /* process whose map is to be loaded */
- 14930 int old_flags; /* value of flags before modification */
- 14931 struct mem_map *map_ptr; /* virtual address of map inside caller (MM) */
- 14932
- 14933 /* Extract message parameters and copy new memory map from MM. */
- 14934 caller = m_ptr->m_source;
- 14935 k = m_ptr->PROC1;
- 14936 map_ptr = (struct mem_map *) m_ptr->MEM_PTR;
- 14937 if (!isokprocn(k)) return(E_BAD_PROC);
- 14938 rp = proc_addr(k); /* ptr to entry of user getting new map */
- 14939
- 14940 /* Copy the map from MM. */
- 14941 src_phys = umap(proc_addr(caller), D, (vir_bytes) map_ptr, sizeof(rp->p_map));
- 14942 if (src_phys == 0) panic("bad call to sys_newmap", NO_NUM);
- 14943 phys_copy(src_phys, vir2phys(rp->p_map), (phys_bytes) sizeof(rp->p_map));
- 14944
- 14945 alloc_segments(rp);
- 14946 old_flags = rp->p_flags; /* save the previous value of the flags */
- 14947 rp->p_flags &= ~NO_MAP;
- 14948 if (old_flags != 0 && rp->p_flags == 0) lock_ready(rp);
- 14949
- 14950 return(OK);
- 14951 }
- 14954 /*===========================================================================*
- 14955 * do_getmap *
- 14956 *===========================================================================*/
- 14957 PRIVATE int do_getmap(m_ptr)
- 14958 message *m_ptr; /* pointer to request message */
- 14959 {
- 14960 /* Handle sys_getmap(). Report the memory map to MM. */
- 14961
- 14962 register struct proc *rp;
- 14963 phys_bytes dst_phys;
- 14964 int caller; /* where the map has to be stored */
- 14965 int k; /* process whose map is to be loaded */
- 14966 struct mem_map *map_ptr; /* virtual address of map inside caller (MM) */
- 14967
- 14968 /* Extract message parameters and copy new memory map to MM. */
- 14969 caller = m_ptr->m_source;
- 14970 k = m_ptr->PROC1;
- 14971 map_ptr = (struct mem_map *) m_ptr->MEM_PTR;
- 14972
- 14973 if (!isokprocn(k))
- 14974 panic("do_getmap got bad proc: ", m_ptr->PROC1);
- 14975
- 14976 rp = proc_addr(k); /* ptr to entry of the map */
- 14977
- 14978 /* Copy the map to MM. */
- 14979 dst_phys = umap(proc_addr(caller), D, (vir_bytes) map_ptr, sizeof(rp->p_map));
- 14980 if (dst_phys == 0) panic("bad call to sys_getmap", NO_NUM);
- 14981 phys_copy(vir2phys(rp->p_map), dst_phys, sizeof(rp->p_map));
- 14982
- 14983 return(OK);
- 14984 }
- 14987 /*===========================================================================*
- 14988 * do_exec *
- 14989 *===========================================================================*/
- 14990 PRIVATE int do_exec(m_ptr)
- 14991 register message *m_ptr; /* pointer to request message */
- 14992 {
- 14993 /* Handle sys_exec(). A process has done a successful EXEC. Patch it up. */
- 14994
- 14995 register struct proc *rp;
- 14996 reg_t sp; /* new sp */
- 14997 phys_bytes phys_name;
- 14998 char *np;
- 14999 #define NLEN (sizeof(rp->p_name)-1)
- 15000
- 15001 if (!isoksusern(m_ptr->PROC1)) return E_BAD_PROC;
- 15002 /* PROC2 field is used as flag to indicate process is being traced */
- 15003 if (m_ptr->PROC2) cause_sig(m_ptr->PROC1, SIGTRAP);
- 15004 sp = (reg_t) m_ptr->STACK_PTR;
- 15005 rp = proc_addr(m_ptr->PROC1);
- 15006 rp->p_reg.sp = sp; /* set the stack pointer */
- 15007 rp->p_reg.pc = (reg_t) m_ptr->IP_PTR; /* set pc */
- 15008 rp->p_alarm = 0; /* reset alarm timer */
- 15009 rp->p_flags &= ~RECEIVING; /* MM does not reply to EXEC call */
- 15010 if (rp->p_flags == 0) lock_ready(rp);
- 15011
- 15012 /* Save command name for debugging, ps(1) output, etc. */
- 15013 phys_name = numap(m_ptr->m_source, (vir_bytes) m_ptr->NAME_PTR,
- 15014 (vir_bytes) NLEN);
- 15015 if (phys_name != 0) {
- 15016 phys_copy(phys_name, vir2phys(rp->p_name), (phys_bytes) NLEN);
- 15017 for (np = rp->p_name; (*np & BYTE) >= ' '; np++) {}
- 15018 *np = 0;
- 15019 }
- 15020 return(OK);
- 15021 }
- 15024 /*===========================================================================*
- 15025 * do_xit *
- 15026 *===========================================================================*/
- 15027 PRIVATE int do_xit(m_ptr)
- 15028 message *m_ptr; /* pointer to request message */
- 15029 {
- 15030 /* Handle sys_xit(). A process has exited. */
- 15031
- 15032 register struct proc *rp, *rc;
- 15033 struct proc *np, *xp;
- 15034 int parent; /* number of exiting proc's parent */
- 15035 int proc_nr; /* number of process doing the exit */
- 15036 phys_clicks base, size;
- 15037
- 15038 parent = m_ptr->PROC1; /* slot number of parent process */
- 15039 proc_nr = m_ptr->PROC2; /* slot number of exiting process */
- 15040 if (!isoksusern(parent) || !isoksusern(proc_nr)) return(E_BAD_PROC);
- 15041 rp = proc_addr(parent);
- 15042 rc = proc_addr(proc_nr);
- 15043 lock();
- 15044 rp->child_utime += rc->user_time + rc->child_utime; /* accum child times */
- 15045 rp->child_stime += rc->sys_time + rc->child_stime;
- 15046 unlock();
- 15047 rc->p_alarm = 0; /* turn off alarm timer */
- 15048 if (rc->p_flags == 0) lock_unready(rc);
- 15049
- 15050 strcpy(rc->p_name, "<noname>"); /* process no longer has a name */
- 15051
- 15052 /* If the process being terminated happens to be queued trying to send a
- 15053 * message (i.e., the process was killed by a signal, rather than it doing an
- 15054 * EXIT), then it must be removed from the message queues.
- 15055 */
- 15056 if (rc->p_flags & SENDING) {
- 15057 /* Check all proc slots to see if the exiting process is queued. */
- 15058 for (rp = BEG_PROC_ADDR; rp < END_PROC_ADDR; rp++) {
- 15059 if (rp->p_callerq == NIL_PROC) continue;
- 15060 if (rp->p_callerq == rc) {
- 15061 /* Exiting process is on front of this queue. */
- 15062 rp->p_callerq = rc->p_sendlink;
- 15063 break;
- 15064 } else {
- 15065 /* See if exiting process is in middle of queue. */
- 15066 np = rp->p_callerq;
- 15067 while ( ( xp = np->p_sendlink) != NIL_PROC)
- 15068 if (xp == rc) {
- 15069 np->p_sendlink = xp->p_sendlink;
- 15070 break;
- 15071 } else {
- 15072 np = xp;
- 15073 }
- 15074 }
- 15075 }
- 15076 }
- 15077
- 15078 if (rc->p_flags & PENDING) --sig_procs;
- 15079 sigemptyset(&rc->p_pending);
- 15080 rc->p_pendcount = 0;
- 15081 rc->p_flags = P_SLOT_FREE;
- 15082 return(OK);
- 15083 }
- 15086 /*===========================================================================*
- 15087 * do_getsp *
- 15088 *===========================================================================*/
- 15089 PRIVATE int do_getsp(m_ptr)
- 15090 register message *m_ptr; /* pointer to request message */
- 15091 {
- 15092 /* Handle sys_getsp(). MM wants to know what sp is. */
- 15093
- 15094 register struct proc *rp;
- 15095
- 15096 if (!isoksusern(m_ptr->PROC1)) return(E_BAD_PROC);
- 15097 rp = proc_addr(m_ptr->PROC1);
- 15098 m_ptr->STACK_PTR = (char *) rp->p_reg.sp; /* return sp here (bad type) */
- 15099 return(OK);
- 15100 }
- 15103 /*===========================================================================*
- 15104 * do_times *
- 15105 *===========================================================================*/
- 15106 PRIVATE int do_times(m_ptr)
- 15107 register message *m_ptr; /* pointer to request message */
- 15108 {
- 15109 /* Handle sys_times(). Retrieve the accounting information. */
- 15110
- 15111 register struct proc *rp;
- 15112
- 15113 if (!isoksusern(m_ptr->PROC1)) return E_BAD_PROC;
- 15114 rp = proc_addr(m_ptr->PROC1);
- 15115
- 15116 /* Insert the times needed by the TIMES system call in the message. */
- 15117 lock(); /* halt the volatile time counters in rp */
- 15118 m_ptr->USER_TIME = rp->user_time;
- 15119 m_ptr->SYSTEM_TIME = rp->sys_time;
- 15120 unlock();
- 15121 m_ptr->CHILD_UTIME = rp->child_utime;
- 15122 m_ptr->CHILD_STIME = rp->child_stime;
- 15123 m_ptr->BOOT_TICKS = get_uptime();
- 15124 return(OK);
- 15125 }
- 15128 /*===========================================================================*
- 15129 * do_abort *
- 15130 *===========================================================================*/
- 15131 PRIVATE int do_abort(m_ptr)
- 15132 message *m_ptr; /* pointer to request message */
- 15133 {
- 15134 /* Handle sys_abort. MINIX is unable to continue. Terminate operation. */
- 15135 char monitor_code[64];
- 15136 phys_bytes src_phys;
- 15137
- 15138 if (m_ptr->m1_i1 == RBT_MONITOR) {
- 15139 /* The monitor is to run user specified instructions. */
- 15140 src_phys = numap(m_ptr->m_source, (vir_bytes) m_ptr->m1_p1,
- 15141 (vir_bytes) sizeof(monitor_code));
- 15142 if (src_phys == 0) panic("bad monitor code from", m_ptr->m_source);
- 15143 phys_copy(src_phys, vir2phys(monitor_code),
- 15144 (phys_bytes) sizeof(monitor_code));
- 15145 reboot_code = vir2phys(monitor_code);
- 15146 }
- 15147 wreboot(m_ptr->m1_i1);
- 15148 return(OK); /* pro-forma (really EDISASTER) */
- 15149 }
- 15154 /*===========================================================================*
- 15155 * do_sendsig *
- 15156 *===========================================================================*/
- 15157 PRIVATE int do_sendsig(m_ptr)
- 15158 message *m_ptr; /* pointer to request message */
- 15159 {
- 15160 /* Handle sys_sendsig, POSIX-style signal */
- 15161
- 15162 struct sigmsg smsg;
- 15163 register struct proc *rp;
- 15164 phys_bytes src_phys, dst_phys;
- 15165 struct sigcontext sc, *scp;
- 15166 struct sigframe fr, *frp;
- 15167
- 15168 if (!isokusern(m_ptr->PROC1)) return(E_BAD_PROC);
- 15169 rp = proc_addr(m_ptr->PROC1);
- 15170
- 15171 /* Get the sigmsg structure into our address space. */
- 15172 src_phys = umap(proc_addr(MM_PROC_NR), D, (vir_bytes) m_ptr->SIG_CTXT_PTR,
- 15173 (vir_bytes) sizeof(struct sigmsg));
- 15174 if (src_phys == 0)
- 15175 panic("do_sendsig can't signal: bad sigmsg address from MM", NO_NUM);
- 15176 phys_copy(src_phys, vir2phys(&smsg), (phys_bytes) sizeof(struct sigmsg));
- 15177
- 15178 /* Compute the usr stack pointer value where sigcontext will be stored. */
- 15179 scp = (struct sigcontext *) smsg.sm_stkptr - 1;
- 15180
- 15181 /* Copy the registers to the sigcontext structure. */
- 15182 memcpy(&sc.sc_regs, &rp->p_reg, sizeof(struct sigregs));
- 15183
- 15184 /* Finish the sigcontext initialization. */
- 15185 sc.sc_flags = SC_SIGCONTEXT;
- 15186
- 15187 sc.sc_mask = smsg.sm_mask;
- 15188
- 15189 /* Copy the sigcontext structure to the user's stack. */
- 15190 dst_phys = umap(rp, D, (vir_bytes) scp,
- 15191 (vir_bytes) sizeof(struct sigcontext));
- 15192 if (dst_phys == 0) return(EFAULT);
- 15193 phys_copy(vir2phys(&sc), dst_phys, (phys_bytes) sizeof(struct sigcontext));
- 15194
- 15195 /* Initialize the sigframe structure. */
- 15196 frp = (struct sigframe *) scp - 1;
- 15197 fr.sf_scpcopy = scp;
- 15198 fr.sf_retadr2= (void (*)()) rp->p_reg.pc;
- 15199 fr.sf_fp = rp->p_reg.fp;
- 15200 rp->p_reg.fp = (reg_t) &frp->sf_fp;
- 15201 fr.sf_scp = scp;
- 15202 fr.sf_code = 0; /* XXX - should be used for type of FP exception */
- 15203 fr.sf_signo = smsg.sm_signo;
- 15204 fr.sf_retadr = (void (*)()) smsg.sm_sigreturn;
- 15205
- 15206 /* Copy the sigframe structure to the user's stack. */
- 15207 dst_phys = umap(rp, D, (vir_bytes) frp, (vir_bytes) sizeof(struct sigframe));
- 15208 if (dst_phys == 0) return(EFAULT);
- 15209 phys_copy(vir2phys(&fr), dst_phys, (phys_bytes) sizeof(struct sigframe));
- 15210
- 15211 /* Reset user registers to execute the signal handler. */
- 15212 rp->p_reg.sp = (reg_t) frp;
- 15213 rp->p_reg.pc = (reg_t) smsg.sm_sighandler;
- 15214
- 15215 return(OK);
- 15216 }
- 15218 /*===========================================================================*
- 15219 * do_sigreturn *
- 15220 *===========================================================================*/
- 15221 PRIVATE int do_sigreturn(m_ptr)
- 15222 register message *m_ptr;
- 15223 {
- 15224 /* POSIX style signals require sys_sigreturn to put things in order before the
- 15225 * signalled process can resume execution
- 15226 */
- 15227
- 15228 struct sigcontext sc;
- 15229 register struct proc *rp;
- 15230 phys_bytes src_phys;
- 15231
- 15232 if (!isokusern(m_ptr->PROC1)) return(E_BAD_PROC);
- 15233 rp = proc_addr(m_ptr->PROC1);
- 15234
- 15235 /* Copy in the sigcontext structure. */
- 15236 src_phys = umap(rp, D, (vir_bytes) m_ptr->SIG_CTXT_PTR,
- 15237 (vir_bytes) sizeof(struct sigcontext));
- 15238 if (src_phys == 0) return(EFAULT);
- 15239 phys_copy(src_phys, vir2phys(&sc), (phys_bytes) sizeof(struct sigcontext));
- 15240
- 15241 /* Make sure that this is not just a jmp_buf. */
- 15242 if ((sc.sc_flags & SC_SIGCONTEXT) == 0) return(EINVAL);
- 15243
- 15244 /* Fix up only certain key registers if the compiler doesn't use
- 15245 * register variables within functions containing setjmp.
- 15246 */
- 15247 if (sc.sc_flags & SC_NOREGLOCALS) {
- 15248 rp->p_reg.retreg = sc.sc_retreg;
- 15249 rp->p_reg.fp = sc.sc_fp;
- 15250 rp->p_reg.pc = sc.sc_pc;
- 15251 rp->p_reg.sp = sc.sc_sp;
- 15252 return (OK);
- 15253 }
- 15254 sc.sc_psw = rp->p_reg.psw;
- 15255
- 15256 #if (CHIP == INTEL)
- 15257 /* Don't panic kernel if user gave bad selectors. */
- 15258 sc.sc_cs = rp->p_reg.cs;
- 15259 sc.sc_ds = rp->p_reg.ds;
- 15260 sc.sc_es = rp->p_reg.es;
- 15261 #if _WORD_SIZE == 4
- 15262 sc.sc_fs = rp->p_reg.fs;
- 15263 sc.sc_gs = rp->p_reg.gs;
- 15264 #endif
- 15265 #endif
- 15266
- 15267 /* Restore the registers. */
- 15268 memcpy(&rp->p_reg, (char *)&sc.sc_regs, sizeof(struct sigregs));
- 15269
- 15270 return(OK);
- 15271 }
- 15273 /*===========================================================================*
- 15274 * do_kill *
- 15275 *===========================================================================*/
- 15276 PRIVATE int do_kill(m_ptr)
- 15277 register message *m_ptr; /* pointer to request message */
- 15278 {
- 15279 /* Handle sys_kill(). Cause a signal to be sent to a process via MM.
- 15280 * Note that this has nothing to do with the kill (2) system call, this
- 15281 * is how the FS (and possibly other servers) get access to cause_sig to
- 15282 * send a KSIG message to MM
- 15283 */
- 15284
- 15285 if (!isokusern(m_ptr->PR)) return(E_BAD_PROC);
- 15286 cause_sig(m_ptr->PR, m_ptr->SIGNUM);
- 15287 return(OK);
- 15288 }
- 15291 /*===========================================================================*
- 15292 * do_endsig *
- 15293 *===========================================================================*/
- 15294 PRIVATE int do_endsig(m_ptr)
- 15295 register message *m_ptr; /* pointer to request message */
- 15296 {
- 15297 /* Finish up after a KSIG-type signal, caused by a SYS_KILL message or a call
- 15298 * to cause_sig by a task
- 15299 */
- 15300
- 15301 register struct proc *rp;
- 15302
- 15303 if (!isokusern(m_ptr->PROC1)) return(E_BAD_PROC);
- 15304 rp = proc_addr(m_ptr->PROC1);
- 15305
- 15306 /* MM has finished one KSIG. */
- 15307 if (rp->p_pendcount != 0 && --rp->p_pendcount == 0
- 15308 && (rp->p_flags &= ~SIG_PENDING) == 0)
- 15309 lock_ready(rp);
- 15310 return(OK);
- 15311 }
- 15313 /*===========================================================================*
- 15314 * do_copy *
- 15315 *===========================================================================*/
- 15316 PRIVATE int do_copy(m_ptr)
- 15317 register message *m_ptr; /* pointer to request message */
- 15318 {
- 15319 /* Handle sys_copy(). Copy data for MM or FS. */
- 15320
- 15321 int src_proc, dst_proc, src_space, dst_space;
- 15322 vir_bytes src_vir, dst_vir;
- 15323 phys_bytes src_phys, dst_phys, bytes;
- 15324
- 15325 /* Dismember the command message. */
- 15326 src_proc = m_ptr->SRC_PROC_NR;
- 15327 dst_proc = m_ptr->DST_PROC_NR;
- 15328 src_space = m_ptr->SRC_SPACE;
- 15329 dst_space = m_ptr->DST_SPACE;
- 15330 src_vir = (vir_bytes) m_ptr->SRC_BUFFER;
- 15331 dst_vir = (vir_bytes) m_ptr->DST_BUFFER;
- 15332 bytes = (phys_bytes) m_ptr->COPY_BYTES;
- 15333
- 15334 /* Compute the source and destination addresses and do the copy. */
- 15335 if (src_proc == ABS)
- 15336 src_phys = (phys_bytes) m_ptr->SRC_BUFFER;
- 15337 else {
- 15338 if (bytes != (vir_bytes) bytes)
- 15339 /* This would happen for 64K segments and 16-bit vir_bytes.
- 15340 * It would happen a lot for do_fork except MM uses ABS
- 15341 * copies for that case.
- 15342 */
- 15343 panic("overflow in count in do_copy", NO_NUM);
- 15344
- 15345 src_phys = umap(proc_addr(src_proc), src_space, src_vir,
- 15346 (vir_bytes) bytes);
- 15347 }
- 15348
- 15349 if (dst_proc == ABS)
- 15350 dst_phys = (phys_bytes) m_ptr->DST_BUFFER;
- 15351 else
- 15352 dst_phys = umap(proc_addr(dst_proc), dst_space, dst_vir,
- 15353 (vir_bytes) bytes);
- 15354
- 15355 if (src_phys == 0 || dst_phys == 0) return(EFAULT);
- 15356 phys_copy(src_phys, dst_phys, bytes);
- 15357 return(OK);
- 15358 }
- 15361 /*===========================================================================*
- 15362 * do_vcopy *
- 15363 *===========================================================================*/
- 15364 PRIVATE int do_vcopy(m_ptr)
- 15365 register message *m_ptr; /* pointer to request message */
- 15366 {
- 15367 /* Handle sys_vcopy(). Copy multiple blocks of memory */
- 15368
- 15369 int src_proc, dst_proc, vect_s, i;
- 15370 vir_bytes src_vir, dst_vir, vect_addr;
- 15371 phys_bytes src_phys, dst_phys, bytes;
- 15372 cpvec_t cpvec_table[CPVEC_NR];
- 15373
- 15374 /* Dismember the command message. */
- 15375 src_proc = m_ptr->m1_i1;
- 15376 dst_proc = m_ptr->m1_i2;
- 15377 vect_s = m_ptr->m1_i3;
- 15378 vect_addr = (vir_bytes)m_ptr->m1_p1;
- 15379
- 15380 if (vect_s > CPVEC_NR) return EDOM;
- 15381
- 15382 src_phys= numap (m_ptr->m_source, vect_addr, vect_s * sizeof(cpvec_t));
- 15383 if (!src_phys) return EFAULT;
- 15384 phys_copy(src_phys, vir2phys(cpvec_table),
- 15385 (phys_bytes) (vect_s * sizeof(cpvec_t)));
- 15386
- 15387 for (i = 0; i < vect_s; i++) {
- 15388 src_vir= cpvec_table[i].cpv_src;
- 15389 dst_vir= cpvec_table[i].cpv_dst;
- 15390 bytes= cpvec_table[i].cpv_size;
- 15391 src_phys = numap(src_proc,src_vir,(vir_bytes)bytes);
- 15392 dst_phys = numap(dst_proc,dst_vir,(vir_bytes)bytes);
- 15393 if (src_phys == 0 || dst_phys == 0) return(EFAULT);
- 15394 phys_copy(src_phys, dst_phys, bytes);
- 15395 }
- 15396 return(OK);
- 15397 }
- 15400 /*==========================================================================*
- 15401 * do_gboot *
- 15402 *==========================================================================*/
- 15403 PUBLIC struct bparam_s boot_parameters;
- 15404
- 15405 PRIVATE int do_gboot(m_ptr)
- 15406 message *m_ptr; /* pointer to request message */
- 15407 {
- 15408 /* Copy the boot parameters. Normally only called during fs init. */
- 15409
- 15410 phys_bytes dst_phys;
- 15411
- 15412 dst_phys = umap(proc_addr(m_ptr->PROC1), D, (vir_bytes) m_ptr->MEM_PTR,
- 15413 (vir_bytes) sizeof(boot_parameters));
- 15414 if (dst_phys == 0) panic("bad call to SYS_GBOOT", NO_NUM);
- 15415 phys_copy(vir2phys(&boot_parameters), dst_phys,
- 15416 (phys_bytes) sizeof(boot_parameters));
- 15417 return(OK);
- 15418 }
- 15421 /*===========================================================================*
- 15422 * do_mem *
- 15423 *===========================================================================*/
- 15424 PRIVATE int do_mem(m_ptr)
- 15425 register message *m_ptr; /* pointer to request message */
- 15426 {
- 15427 /* Return the base and size of the next chunk of memory. */
- 15428
- 15429 struct memory *memp;
- 15430
- 15431 for (memp = mem; memp < &mem[NR_MEMS]; ++memp) {
- 15432 m_ptr->m1_i1 = memp->base;
- 15433 m_ptr->m1_i2 = memp->size;
- 15434 m_ptr->m1_i3 = tot_mem_size;
- 15435 memp->size = 0;
- 15436 if (m_ptr->m1_i2 != 0) break; /* found a chunk */
- 15437 }
- 15438 return(OK);
- 15439 }
- 15442 /*==========================================================================*
- 15443 * do_umap *
- 15444 *==========================================================================*/
- 15445 PRIVATE int do_umap(m_ptr)
- 15446 register message *m_ptr; /* pointer to request message */
- 15447 {
- 15448 /* Same as umap(), for non-kernel processes. */
- 15449
- 15450 m_ptr->SRC_BUFFER = umap(proc_addr((int) m_ptr->SRC_PROC_NR),
- 15451 (int) m_ptr->SRC_SPACE,
- 15452 (vir_bytes) m_ptr->SRC_BUFFER,
- 15453 (vir_bytes) m_ptr->COPY_BYTES);
- 15454 return(OK);
- 15455 }
- 15458 /*==========================================================================*
- 15459 * do_trace *
- 15460 *==========================================================================*/
- 15461 #define TR_PROCNR (m_ptr->m2_i1)
- 15462 #define TR_REQUEST (m_ptr->m2_i2)
- 15463 #define TR_ADDR ((vir_bytes) m_ptr->m2_l1)
- 15464 #define TR_DATA (m_ptr->m2_l2)
- 15465 #define TR_VLSIZE ((vir_bytes) sizeof(long))
- 15466
- 15467 PRIVATE int do_trace(m_ptr)
- 15468 register message *m_ptr;
- 15469 {
- 15470 /* Handle the debugging commands supported by the ptrace system call
- 15471 * The commands are:
- 15472 * T_STOP stop the process
- 15473 * T_OK enable tracing by parent for this process
- 15474 * T_GETINS return value from instruction space
- 15475 * T_GETDATA return value from data space
- 15476 * T_GETUSER return value from user process table
- 15477 * T_SETINS set value from instruction space
- 15478 * T_SETDATA set value from data space
- 15479 * T_SETUSER set value in user process table
- 15480 * T_RESUME resume execution
- 15481 * T_EXIT exit
- 15482 * T_STEP set trace bit
- 15483 *
- 15484 * The T_OK and T_EXIT commands are handled completely by the memory manager,
- 15485 * all others come here.
- 15486 */
- 15487
- 15488 register struct proc *rp;
- 15489 phys_bytes src, dst;
- 15490 int i;
- 15491
- 15492 rp = proc_addr(TR_PROCNR);
- 15493 if (rp->p_flags & P_SLOT_FREE) return(EIO);
- 15494 switch (TR_REQUEST) {
- 15495 case T_STOP: /* stop process */
- 15496 if (rp->p_flags == 0) lock_unready(rp);
- 15497 rp->p_flags |= P_STOP;
- 15498 rp->p_reg.psw &= ~TRACEBIT; /* clear trace bit */
- 15499 return(OK);
- 15500
- 15501 case T_GETINS: /* return value from instruction space */
- 15502 if (rp->p_map[T].mem_len != 0) {
- 15503 if ((src = umap(rp, T, TR_ADDR, TR_VLSIZE)) == 0) return(EIO);
- 15504 phys_copy(src, vir2phys(&TR_DATA), (phys_bytes) sizeof(long));
- 15505 break;
- 15506 }
- 15507 /* Text space is actually data space - fall through. */
- 15508
- 15509 case T_GETDATA: /* return value from data space */
- 15510 if ((src = umap(rp, D, TR_ADDR, TR_VLSIZE)) == 0) return(EIO);
- 15511 phys_copy(src, vir2phys(&TR_DATA), (phys_bytes) sizeof(long));
- 15512 break;
- 15513
- 15514 case T_GETUSER: /* return value from process table */
- 15515 if ((TR_ADDR & (sizeof(long) - 1)) != 0 ||
- 15516 TR_ADDR > sizeof(struct proc) - sizeof(long))
- 15517 return(EIO);
- 15518 TR_DATA = *(long *) ((char *) rp + (int) TR_ADDR);
- 15519 break;
- 15520
- 15521 case T_SETINS: /* set value in instruction space */
- 15522 if (rp->p_map[T].mem_len != 0) {
- 15523 if ((dst = umap(rp, T, TR_ADDR, TR_VLSIZE)) == 0) return(EIO);
- 15524 phys_copy(vir2phys(&TR_DATA), dst, (phys_bytes) sizeof(long));
- 15525 TR_DATA = 0;
- 15526 break;
- 15527 }
- 15528 /* Text space is actually data space - fall through. */
- 15529
- 15530 case T_SETDATA: /* set value in data space */
- 15531 if ((dst = umap(rp, D, TR_ADDR, TR_VLSIZE)) == 0) return(EIO);
- 15532 phys_copy(vir2phys(&TR_DATA), dst, (phys_bytes) sizeof(long));
- 15533 TR_DATA = 0;
- 15534 break;
- 15535
- 15536 case T_SETUSER: /* set value in process table */
- 15537 if ((TR_ADDR & (sizeof(reg_t) - 1)) != 0 ||
- 15538 TR_ADDR > sizeof(struct stackframe_s) - sizeof(reg_t))
- 15539 return(EIO);
- 15540 i = (int) TR_ADDR;
- 15541 #if (CHIP == INTEL)
- 15542 /* Altering segment registers might crash the kernel when it
- 15543 * tries to load them prior to restarting a process, so do
- 15544 * not allow it.
- 15545 */
- 15546 if (i == (int) &((struct proc *) 0)->p_reg.cs ||
- 15547 i == (int) &((struct proc *) 0)->p_reg.ds ||
- 15548 i == (int) &((struct proc *) 0)->p_reg.es ||
- 15549 #if _WORD_SIZE == 4
- 15550 i == (int) &((struct proc *) 0)->p_reg.gs ||
- 15551 i == (int) &((struct proc *) 0)->p_reg.fs ||
- 15552 #endif
- 15553 i == (int) &((struct proc *) 0)->p_reg.ss)
- 15554 return(EIO);
- 15555 #endif
- 15556 if (i == (int) &((struct proc *) 0)->p_reg.psw)
- 15557 /* only selected bits are changeable */
- 15558 SETPSW(rp, TR_DATA);
- 15559 else
- 15560 *(reg_t *) ((char *) &rp->p_reg + i) = (reg_t) TR_DATA;
- 15561 TR_DATA = 0;
- 15562 break;
- 15563
- 15564 case T_RESUME: /* resume execution */
- 15565 rp->p_flags &= ~P_STOP;
- 15566 if (rp->p_flags == 0) lock_ready(rp);
- 15567 TR_DATA = 0;
- 15568 break;
- 15569
- 15570 case T_STEP: /* set trace bit */
- 15571 rp->p_reg.psw |= TRACEBIT;
- 15572 rp->p_flags &= ~P_STOP;
- 15573 if (rp->p_flags == 0) lock_ready(rp);
- 15574 TR_DATA = 0;
- 15575 break;
- 15576
- 15577 default:
- 15578 return(EIO);
- 15579 }
- 15580 return(OK);
- 15581 }
- 15583 /*===========================================================================*
- 15584 * cause_sig *
- 15585 *===========================================================================*/
- 15586 PUBLIC void cause_sig(proc_nr, sig_nr)
- 15587 int proc_nr; /* process to be signalled */
- 15588 int sig_nr; /* signal to be sent, 1 to _NSIG */
- 15589 {
- 15590 /* A task wants to send a signal to a process. Examples of such tasks are:
- 15591 * TTY wanting to cause SIGINT upon getting a DEL
- 15592 * CLOCK wanting to cause SIGALRM when timer expires
- 15593 * FS also uses this to send a signal, via the SYS_KILL message.
- 15594 * Signals are handled by sending a message to MM. The tasks don't dare do
- 15595 * that directly, for fear of what would happen if MM were busy. Instead they
- 15596 * call cause_sig, which sets bits in p_pending, and then carefully checks to
- 15597 * see if MM is free. If so, a message is sent to it. If not, when it becomes
- 15598 * free, a message is sent. The process being signaled is blocked while MM
- 15599 * has not seen or finished with all signals for it. These signals are
- 15600 * counted in p_pendcount, and the SIG_PENDING flag is kept nonzero while
- 15601 * there are some. It is not sufficient to ready the process when MM is
- 15602 * informed, because MM can block waiting for FS to do a core dump.
- 15603 */
- 15604
- 15605 register struct proc *rp, *mmp;
- 15606
- 15607 rp = proc_addr(proc_nr);
- 15608 if (sigismember(&rp->p_pending, sig_nr))
- 15609 return; /* this signal already pending */
- 15610 sigaddset(&rp->p_pending, sig_nr);
- 15611 ++rp->p_pendcount; /* count new signal pending */
- 15612 if (rp->p_flags & PENDING)
- 15613 return; /* another signal already pending */
- 15614 if (rp->p_flags == 0) lock_unready(rp);
- 15615 rp->p_flags |= PENDING | SIG_PENDING;
- 15616 ++sig_procs; /* count new process pending */
- 15617
- 15618 mmp = proc_addr(MM_PROC_NR);
- 15619 if ( ((mmp->p_flags & RECEIVING) == 0) || mmp->p_getfrom != ANY) return;
- 15620 inform();
- 15621 }
- 15624 /*===========================================================================*
- 15625 * inform *
- 15626 *===========================================================================*/
- 15627 PUBLIC void inform()
- 15628 {
- 15629 /* When a signal is detected by the kernel (e.g., DEL), or generated by a task
- 15630 * (e.g. clock task for SIGALRM), cause_sig() is called to set a bit in the
- 15631 * p_pending field of the process to signal. Then inform() is called to see
- 15632 * if MM is idle and can be told about it. Whenever MM blocks, a check is
- 15633 * made to see if 'sig_procs' is nonzero; if so, inform() is called.
- 15634 */
- 15635
- 15636 register struct proc *rp;
- 15637
- 15638 /* MM is waiting for new input. Find a process with pending signals. */
- 15639 for (rp = BEG_SERV_ADDR; rp < END_PROC_ADDR; rp++)
- 15640 if (rp->p_flags & PENDING) {
- 15641 m.m_type = KSIG;
- 15642 m.SIG_PROC = proc_number(rp);
- 15643 m.SIG_MAP = rp->p_pending;
- 15644 sig_procs--;
- 15645 if (lock_mini_send(proc_addr(HARDWARE), MM_PROC_NR, &m) != OK)
- 15646 panic("can't inform MM", NO_NUM);
- 15647 sigemptyset(&rp->p_pending); /* the ball is now in MM's court */
- 15648 rp->p_flags &= ~PENDING;/* remains inhibited by SIG_PENDING */
- 15649 lock_pick_proc(); /* avoid delay in scheduling MM */
- 15650 return;
- 15651 }
- 15652 }
- 15655 /*===========================================================================*
- 15656 * umap *
- 15657 *===========================================================================*/
- 15658 PUBLIC phys_bytes umap(rp, seg, vir_addr, bytes)
- 15659 register struct proc *rp; /* pointer to proc table entry for process */
- 15660 int seg; /* T, D, or S segment */
- 15661 vir_bytes vir_addr; /* virtual address in bytes within the seg */
- 15662 vir_bytes bytes; /* # of bytes to be copied */
- 15663 {
- 15664 /* Calculate the physical memory address for a given virtual address. */
- 15665
- 15666 vir_clicks vc; /* the virtual address in clicks */
- 15667 phys_bytes pa; /* intermediate variables as phys_bytes */
- 15668 phys_bytes seg_base;
- 15669
- 15670 /* If 'seg' is D it could really be S and vice versa. T really means T.
- 15671 * If the virtual address falls in the gap, it causes a problem. On the
- 15672 * 8088 it is probably a legal stack reference, since "stackfaults" are
- 15673 * not detected by the hardware. On 8088s, the gap is called S and
- 15674 * accepted, but on other machines it is called D and rejected.
- 15675 * The Atari ST behaves like the 8088 in this respect.
- 15676 */
- 15677
- 15678 if (bytes <= 0) return( (phys_bytes) 0);
- 15679 vc = (vir_addr + bytes - 1) >> CLICK_SHIFT; /* last click of data */
- 15680
- 15681 if (seg != T)
- 15682 seg = (vc < rp->p_map[D].mem_vir + rp->p_map[D].mem_len ? D : S);
- 15683
- 15684 if((vir_addr>>CLICK_SHIFT) >= rp->p_map[seg].mem_vir+ rp->p_map[seg].mem_len)
- 15685 return( (phys_bytes) 0 );
- 15686 seg_base = (phys_bytes) rp->p_map[seg].mem_phys;
- 15687 seg_base = seg_base << CLICK_SHIFT; /* segment origin in bytes */
- 15688 pa = (phys_bytes) vir_addr;
- 15689 pa -= rp->p_map[seg].mem_vir << CLICK_SHIFT;
- 15690 return(seg_base + pa);
- 15691 }
- 15694 /*==========================================================================*
- 15695 * numap *
- 15696 *==========================================================================*/
- 15697 PUBLIC phys_bytes numap(proc_nr, vir_addr, bytes)
- 15698 int proc_nr; /* process number to be mapped */
- 15699 vir_bytes vir_addr; /* virtual address in bytes within D seg */
- 15700 vir_bytes bytes; /* # of bytes required in segment */
- 15701 {
- 15702 /* Do umap() starting from a process number instead of a pointer. This
- 15703 * function is used by device drivers, so they need not know about the
- 15704 * process table. To save time, there is no 'seg' parameter. The segment
- 15705 * is always D.
- 15706 */
- 15707
- 15708 return(umap(proc_addr(proc_nr), D, vir_addr, bytes));
- 15709 }
- 15711 #if (CHIP == INTEL)
- 15712 /*==========================================================================*
- 15713 * alloc_segments *
- 15714 *==========================================================================*/
- 15715 PUBLIC void alloc_segments(rp)
- 15716 register struct proc *rp;
- 15717 {
- 15718 /* This is called only by do_newmap, but is broken out as a separate function
- 15719 * because so much is hardware-dependent.
- 15720 */
- 15721
- 15722 phys_bytes code_bytes;
- 15723 phys_bytes data_bytes;
- 15724 int privilege;
- 15725
- 15726 if (protected_mode) {
- 15727 data_bytes = (phys_bytes) (rp->p_map[S].mem_vir + rp->p_map[S].mem_len)
- 15728 << CLICK_SHIFT;
- 15729 if (rp->p_map[T].mem_len == 0)
- 15730 code_bytes = data_bytes; /* common I&D, poor protect */
- 15731 else
- 15732 code_bytes = (phys_bytes) rp->p_map[T].mem_len << CLICK_SHIFT;
- 15733 privilege = istaskp(rp) ? TASK_PRIVILEGE : USER_PRIVILEGE;
- 15734 init_codeseg(&rp->p_ldt[CS_LDT_INDEX],
- 15735 (phys_bytes) rp->p_map[T].mem_phys << CLICK_SHIFT,
- 15736 code_bytes, privilege);
- 15737 init_dataseg(&rp->p_ldt[DS_LDT_INDEX],
- 15738 (phys_bytes) rp->p_map[D].mem_phys << CLICK_SHIFT,
- 15739 data_bytes, privilege);
- 15740 rp->p_reg.cs = (CS_LDT_INDEX * DESC_SIZE) | TI | privilege;
- 15741 #if _WORD_SIZE == 4
- 15742 rp->p_reg.gs =
- 15743 rp->p_reg.fs =
- 15744 #endif
- 15745 rp->p_reg.ss =
- 15746 rp->p_reg.es =
- 15747 rp->p_reg.ds = (DS_LDT_INDEX*DESC_SIZE) | TI | privilege;
- 15748 } else {
- 15749 rp->p_reg.cs = click_to_hclick(rp->p_map[T].mem_phys);
- 15750 rp->p_reg.ss =
- 15751 rp->p_reg.es =
- 15752 rp->p_reg.ds = click_to_hclick(rp->p_map[D].mem_phys);
- 15753 }
- 15754 }
- 15755 #endif /* (CHIP == INTEL) */
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- src/mm/mm.h
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- 15800 /* This is the master header for mm. It includes some other files
- 15801 * and defines the principal constants.
- 15802 */
- 15803 #define _POSIX_SOURCE 1 /* tell headers to include POSIX stuff */
- 15804 #define _MINIX 1 /* tell headers to include MINIX stuff */
- 15805 #define _SYSTEM 1 /* tell headers that this is the kernel */
- 15806
- 15807 /* The following are so basic, all the *.c files get them automatically. */
- 15808 #include <minix/config.h> /* MUST be first */
- 15809 #include <ansi.h> /* MUST be second */
- 15810 #include <sys/types.h>
- 15811 #include <minix/const.h>
- 15812 #include <minix/type.h>
- 15813
- 15814 #include <fcntl.h>
- 15815 #include <unistd.h>
- 15816 #include <minix/syslib.h>
- 15817
- 15818 #include <limits.h>
- 15819 #include <errno.h>
- 15820
- 15821 #include "const.h"
- 15822 #include "type.h"
- 15823 #include "proto.h"
- 15824 #include "glo.h"
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- src/mm/const.h
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- 15900 /* Constants used by the Memory Manager. */
- 15901
- 15902 #define NO_MEM ((phys_clicks) 0) /* returned by alloc_mem() with mem is up */
- 15903
- 15904 #if (CHIP == INTEL && _WORD_SIZE == 2)
- 15905 /* These definitions are used in size_ok and are not needed for 386.
- 15906 * The 386 segment granularity is 1 for segments smaller than 1M and 4096
- 15907 * above that.
- 15908 */
- 15909 #define PAGE_SIZE 16 /* how many bytes in a page (s.b.HCLICK_SIZE)*/
- 15910 #define MAX_PAGES 4096 /* how many pages in the virtual addr space */
- 15911 #endif
- 15912
- 15913 #define printf printk
- 15914
- 15915 #define INIT_PID 1 /* init's process id number */
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- src/mm/type.h
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- 16000 /* If there were any type definitions local to the Memory Manager, they would
- 16001 * be here. This file is included only for symmetry with the kernel and File
- 16002 * System, which do have some local type definitions.
- 16003 */
- 16004
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- src/mm/proto.h
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- 16100 /* Function prototypes. */
- 16101
- 16102 struct mproc; /* need types outside of parameter list --kub */
- 16103 struct stat;
- 16104
- 16105 /* alloc.c */
- 16106 _PROTOTYPE( phys_clicks alloc_mem, (phys_clicks clicks) );
- 16107 _PROTOTYPE( void free_mem, (phys_clicks base, phys_clicks clicks) );
- 16108 _PROTOTYPE( phys_clicks max_hole, (void) );
- 16109 _PROTOTYPE( void mem_init, (phys_clicks *total, phys_clicks *free) );
- 16110 _PROTOTYPE( phys_clicks mem_left, (void) );
- 16111 _PROTOTYPE( int do_brk3, (void) );
- 16112
- 16113 /* break.c */
- 16114 _PROTOTYPE( int adjust, (struct mproc *rmp,
- 16115 vir_clicks data_clicks, vir_bytes sp) );
- 16116 _PROTOTYPE( int do_brk, (void) );
- 16117 _PROTOTYPE( int size_ok, (int file_type, vir_clicks tc, vir_clicks dc,
- 16118 vir_clicks sc, vir_clicks dvir, vir_clicks s_vir) );
- 16119
- 16120 /* exec.c */
- 16121 _PROTOTYPE( int do_exec, (void) );
- 16122 _PROTOTYPE( struct mproc *find_share, (struct mproc *mp_ign, Ino_t ino,
- 16123 Dev_t dev, time_t ctime) );
- 16124
- 16125 /* forkexit.c */
- 16126 _PROTOTYPE( int do_fork, (void) );
- 16127 _PROTOTYPE( int do_mm_exit, (void) );
- 16128 _PROTOTYPE( int do_waitpid, (void) );
- 16129 _PROTOTYPE( void mm_exit, (struct mproc *rmp, int exit_status) );
- 16130
- 16131 /* getset.c */
- 16132 _PROTOTYPE( int do_getset, (void) );
- 16133
- 16134 /* main.c */
- 16135 _PROTOTYPE( void main, (void) );
- 16136
- 16137 #if (MACHINE == MACINTOSH)
- 16138 _PROTOTYPE( phys_clicks start_click, (void) );
- 16139 #endif
- 16140
- 16141 _PROTOTYPE( void reply, (int proc_nr, int result, int res2, char *respt));
- 16142
- 16143 /* putk.c */
- 16144 _PROTOTYPE( void putk, (int c) );
- 16145
- 16146 /* signal.c */
- 16147 _PROTOTYPE( int do_alarm, (void) );
- 16148 _PROTOTYPE( int do_kill, (void) );
- 16149 _PROTOTYPE( int do_ksig, (void) );
- 16150 _PROTOTYPE( int do_pause, (void) );
- 16151 _PROTOTYPE( int set_alarm, (int proc_nr, int sec) );
- 16152 _PROTOTYPE( int check_sig, (pid_t proc_id, int signo) );
- 16153 _PROTOTYPE( void sig_proc, (struct mproc *rmp, int sig_nr) );
- 16154 _PROTOTYPE( int do_sigaction, (void) );
- 16155 _PROTOTYPE( int do_sigpending, (void) );
- 16156 _PROTOTYPE( int do_sigprocmask, (void) );
- 16157 _PROTOTYPE( int do_sigreturn, (void) );
- 16158 _PROTOTYPE( int do_sigsuspend, (void) );
- 16159 _PROTOTYPE( int do_reboot, (void) );
- 16160
- 16161 /* trace.c */
- 16162 _PROTOTYPE( int do_trace, (void) );
- 16163 _PROTOTYPE( void stop_proc, (struct mproc *rmp, int sig_nr) );
- 16164
- 16165 /* utility.c */
- 16166 _PROTOTYPE( int allowed, (char *name_buf, struct stat *s_buf, int mask) );
- 16167 _PROTOTYPE( int no_sys, (void) );
- 16168 _PROTOTYPE( void panic, (char *format, int num) );
- 16169 _PROTOTYPE( void tell_fs, (int what, int p1, int p2, int p3) );
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- src/mm/glo.h
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- 16200 /* EXTERN should be extern except in table.c */
- 16201 #ifdef _TABLE
- 16202 #undef EXTERN
- 16203 #define EXTERN
- 16204 #endif
- 16205
- 16206 /* Global variables. */
- 16207 EXTERN struct mproc *mp; /* ptr to 'mproc' slot of current process */
- 16208 EXTERN int dont_reply; /* normally 0; set to 1 to inhibit reply */
- 16209 EXTERN int procs_in_use; /* how many processes are marked as IN_USE */
- 16210
- 16211 /* The parameters of the call are kept here. */
- 16212 EXTERN message mm_in; /* the incoming message itself is kept here. */
- 16213 EXTERN message mm_out; /* the reply message is built up here. */
- 16214 EXTERN int who; /* caller's proc number */
- 16215 EXTERN int mm_call; /* system call number */
- 16216
- 16217 /* The following variables are used for returning results to the caller. */
- 16218 EXTERN int err_code; /* temporary storage for error number */
- 16219 EXTERN int result2; /* secondary result */
- 16220 EXTERN char *res_ptr; /* result, if pointer */
- 16221
- 16222 extern _PROTOTYPE (int (*call_vec[]), (void) ); /* system call handlers */
- 16223 extern char core_name[]; /* file name where core images are produced */
- 16224 EXTERN sigset_t core_sset; /* which signals cause core images */
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- src/mm/mproc.h
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- 16300 /* This table has one slot per process. It contains all the memory management
- 16301 * information for each process. Among other things, it defines the text, data
- 16302 * and stack segments, uids and gids, and various flags. The kernel and file
- 16303 * systems have tables that are also indexed by process, with the contents
- 16304 * of corresponding slots referring to the same process in all three.
- 16305 */
- 16306
- 16307 EXTERN struct mproc {
- 16308 struct mem_map mp_seg[NR_SEGS];/* points to text, data, stack */
- 16309 char mp_exitstatus; /* storage for status when process exits */
- 16310 char mp_sigstatus; /* storage for signal # for killed procs */
- 16311 pid_t mp_pid; /* process id */
- 16312 pid_t mp_procgrp; /* pid of process group (used for signals) */
- 16313 pid_t mp_wpid; /* pid this process is waiting for */
- 16314 int mp_parent; /* index of parent process */
- 16315
- 16316 /* Real and effective uids and gids. */
- 16317 uid_t mp_realuid; /* process' real uid */
- 16318 uid_t mp_effuid; /* process' effective uid */
- 16319 gid_t mp_realgid; /* process' real gid */
- 16320 gid_t mp_effgid; /* process' effective gid */
- 16321
- 16322 /* File identification for sharing. */
- 16323 ino_t mp_ino; /* inode number of file */
- 16324 dev_t mp_dev; /* device number of file system */
- 16325 time_t mp_ctime; /* inode changed time */
- 16326
- 16327 /* Signal handling information. */
- 16328 sigset_t mp_ignore; /* 1 means ignore the signal, 0 means don't */
- 16329 sigset_t mp_catch; /* 1 means catch the signal, 0 means don't */
- 16330 sigset_t mp_sigmask; /* signals to be blocked */
- 16331 sigset_t mp_sigmask2; /* saved copy of mp_sigmask */
- 16332 sigset_t mp_sigpending; /* signals being blocked */
- 16333 struct sigaction mp_sigact[_NSIG + 1]; /* as in sigaction(2) */
- 16334 vir_bytes mp_sigreturn; /* address of C library __sigreturn function */
- 16335
- 16336 /* Backwards compatibility for signals. */
- 16337 sighandler_t mp_func; /* all sigs vectored to a single user fcn */
- 16338
- 16339 unsigned mp_flags; /* flag bits */
- 16340 vir_bytes mp_procargs; /* ptr to proc's initial stack arguments */
- 16341 } mproc[NR_PROCS];
- 16342
- 16343 /* Flag values */
- 16344 #define IN_USE 001 /* set when 'mproc' slot in use */
- 16345 #define WAITING 002 /* set by WAIT system call */
- 16346 #define HANGING 004 /* set by EXIT system call */
- 16347 #define PAUSED 010 /* set by PAUSE system call */
- 16348 #define ALARM_ON 020 /* set when SIGALRM timer started */
- 16349 #define SEPARATE 040 /* set if file is separate I & D space */
- 16350 #define TRACED 0100 /* set if process is to be traced */
- 16351 #define STOPPED 0200 /* set if process stopped for tracing */
- 16352 #define SIGSUSPENDED 0400 /* set by SIGSUSPEND system call */
- 16353
- 16354 #define NIL_MPROC ((struct mproc *) 0)
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- src/mm/param.h
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- 16400 /* The following names are synonyms for the variables in the input message. */
- 16401 #define addr mm_in.m1_p1
- 16402 #define exec_name mm_in.m1_p1
- 16403 #define exec_len mm_in.m1_i1
- 16404 #define func mm_in.m6_f1
- 16405 #define grpid (gid_t) mm_in.m1_i1
- 16406 #define namelen mm_in.m1_i1
- 16407 #define pid mm_in.m1_i1
- 16408 #define seconds mm_in.m1_i1
- 16409 #define sig mm_in.m6_i1
- 16410 #define stack_bytes mm_in.m1_i2
- 16411 #define stack_ptr mm_in.m1_p2
- 16412 #define status mm_in.m1_i1
- 16413 #define usr_id (uid_t) mm_in.m1_i1
- 16414 #define request mm_in.m2_i2
- 16415 #define taddr mm_in.m2_l1
- 16416 #define data mm_in.m2_l2
- 16417 #define sig_nr mm_in.m1_i2
- 16418 #define sig_nsa mm_in.m1_p1
- 16419 #define sig_osa mm_in.m1_p2
- 16420 #define sig_ret mm_in.m1_p3
- 16421 #define sig_set mm_in.m2_l1
- 16422 #define sig_how mm_in.m2_i1
- 16423 #define sig_flags mm_in.m2_i2
- 16424 #define sig_context mm_in.m2_p1
- 16425 #ifdef _SIGMESSAGE
- 16426 #define sig_msg mm_in.m1_i1
- 16427 #endif
- 16428 #define reboot_flag mm_in.m1_i1
- 16429 #define reboot_code mm_in.m1_p1
- 16430 #define reboot_size mm_in.m1_i2
- 16431
- 16432 /* The following names are synonyms for the variables in the output message. */
- 16433 #define reply_type mm_out.m_type
- 16434 #define reply_i1 mm_out.m2_i1
- 16435 #define reply_p1 mm_out.m2_p1
- 16436 #define ret_mask mm_out.m2_l1
- 16437
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- src/mm/table.c
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- 16500 /* This file contains the table used to map system call numbers onto the
- 16501 * routines that perform them.
- 16502 */
- 16503
- 16504 #define _TABLE
- 16505
- 16506 #include "mm.h"
- 16507 #include <minix/callnr.h>
- 16508 #include <signal.h>
- 16509 #include "mproc.h"
- 16510 #include "param.h"
- 16511
- 16512 /* Miscellaneous */
- 16513 char core_name[] = "core"; /* file name where core images are produced */
- 16514
- 16515 _PROTOTYPE (int (*call_vec[NCALLS]), (void) ) = {
- 16516 no_sys, /* 0 = unused */
- 16517 do_mm_exit, /* 1 = exit */
- 16518 do_fork, /* 2 = fork */
- 16519 no_sys, /* 3 = read */
- 16520 no_sys, /* 4 = write */
- 16521 no_sys, /* 5 = open */
- 16522 no_sys, /* 6 = close */
- 16523 do_waitpid, /* 7 = wait */
- 16524 no_sys, /* 8 = creat */
- 16525 no_sys, /* 9 = link */
- 16526 no_sys, /* 10 = unlink */
- 16527 do_waitpid, /* 11 = waitpid */
- 16528 no_sys, /* 12 = chdir */
- 16529 no_sys, /* 13 = time */
- 16530 no_sys, /* 14 = mknod */
- 16531 no_sys, /* 15 = chmod */
- 16532 no_sys, /* 16 = chown */
- 16533 do_brk, /* 17 = break */
- 16534 no_sys, /* 18 = stat */
- 16535 no_sys, /* 19 = lseek */
- 16536 do_getset, /* 20 = getpid */
- 16537 no_sys, /* 21 = mount */
- 16538 no_sys, /* 22 = umount */
- 16539 do_getset, /* 23 = setuid */
- 16540 do_getset, /* 24 = getuid */
- 16541 no_sys, /* 25 = stime */
- 16542 do_trace, /* 26 = ptrace */
- 16543 do_alarm, /* 27 = alarm */
- 16544 no_sys, /* 28 = fstat */
- 16545 do_pause, /* 29 = pause */
- 16546 no_sys, /* 30 = utime */
- 16547 no_sys, /* 31 = (stty) */
- 16548 no_sys, /* 32 = (gtty) */
- 16549 no_sys, /* 33 = access */
- 16550 no_sys, /* 34 = (nice) */
- 16551 no_sys, /* 35 = (ftime) */
- 16552 no_sys, /* 36 = sync */
- 16553 do_kill, /* 37 = kill */
- 16554 no_sys, /* 38 = rename */
- 16555 no_sys, /* 39 = mkdir */
- 16556 no_sys, /* 40 = rmdir */
- 16557 no_sys, /* 41 = dup */
- 16558 no_sys, /* 42 = pipe */
- 16559 no_sys, /* 43 = times */
- 16560 no_sys, /* 44 = (prof) */
- 16561 no_sys, /* 45 = unused */
- 16562 do_getset, /* 46 = setgid */
- 16563 do_getset, /* 47 = getgid */
- 16564 no_sys, /* 48 = (signal)*/
- 16565 no_sys, /* 49 = unused */
- 16566 no_sys, /* 50 = unused */
- 16567 no_sys, /* 51 = (acct) */
- 16568 no_sys, /* 52 = (phys) */
- 16569 no_sys, /* 53 = (lock) */
- 16570 no_sys, /* 54 = ioctl */
- 16571 no_sys, /* 55 = fcntl */
- 16572 no_sys, /* 56 = (mpx) */
- 16573 no_sys, /* 57 = unused */
- 16574 no_sys, /* 58 = unused */
- 16575 do_exec, /* 59 = execve */
- 16576 no_sys, /* 60 = umask */
- 16577 no_sys, /* 61 = chroot */
- 16578 do_getset, /* 62 = setsid */
- 16579 do_getset, /* 63 = getpgrp */
- 16580
- 16581 do_ksig, /* 64 = KSIG: signals originating in the kernel */
- 16582 no_sys, /* 65 = UNPAUSE */
- 16583 no_sys, /* 66 = unused */
- 16584 no_sys, /* 67 = REVIVE */
- 16585 no_sys, /* 68 = TASK_REPLY */
- 16586 no_sys, /* 69 = unused */
- 16587 no_sys, /* 70 = unused */
- 16588 do_sigaction, /* 71 = sigaction */
- 16589 do_sigsuspend, /* 72 = sigsuspend */
- 16590 do_sigpending, /* 73 = sigpending */
- 16591 do_sigprocmask, /* 74 = sigprocmask */
- 16592 do_sigreturn, /* 75 = sigreturn */
- 16593 do_reboot, /* 76 = reboot */
- 16594 };
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- src/mm/main.c
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- 16600 /* This file contains the main program of the memory manager and some related
- 16601 * procedures. When MINIX starts up, the kernel runs for a little while,
- 16602 * initializing itself and its tasks, and then it runs MM and FS. Both MM
- 16603 * and FS initialize themselves as far as they can. FS then makes a call to
- 16604 * MM, because MM has to wait for FS to acquire a RAM disk. MM asks the
- 16605 * kernel for all free memory and starts serving requests.
- 16606 *
- 16607 * The entry points into this file are:
- 16608 * main: starts MM running
- 16609 * reply: reply to a process making an MM system call
- 16610 */
- 16611
- 16612 #include "mm.h"
- 16613 #include <minix/callnr.h>
- 16614 #include <minix/com.h>
- 16615 #include <signal.h>
- 16616 #include <fcntl.h>
- 16617 #include <sys/ioctl.h>
- 16618 #include "mproc.h"
- 16619 #include "param.h"
- 16620
- 16621 FORWARD _PROTOTYPE( void get_work, (void) );
- 16622 FORWARD _PROTOTYPE( void mm_init, (void) );
- 16623
- 16624 /*===========================================================================*
- 16625 * main *
- 16626 *===========================================================================*/
- 16627 PUBLIC void main()
- 16628 {
- 16629 /* Main routine of the memory manager. */
- 16630
- 16631 int error;
- 16632
- 16633 mm_init(); /* initialize memory manager tables */
- 16634
- 16635 /* This is MM's main loop- get work and do it, forever and forever. */
- 16636 while (TRUE) {
- 16637 /* Wait for message. */
- 16638 get_work(); /* wait for an MM system call */
- 16639 mp = &mproc[who];
- 16640
- 16641 /* Set some flags. */
- 16642 error = OK;
- 16643 dont_reply = FALSE;
- 16644 err_code = -999;
- 16645
- 16646 /* If the call number is valid, perform the call. */
- 16647 if (mm_call < 0 || mm_call >= NCALLS)
- 16648 error = EBADCALL;
- 16649 else
- 16650 error = (*call_vec[mm_call])();
- 16651
- 16652 /* Send the results back to the user to indicate completion. */
- 16653 if (dont_reply) continue; /* no reply for EXIT and WAIT */
- 16654 if (mm_call == EXEC && error == OK) continue;
- 16655 reply(who, error, result2, res_ptr);
- 16656 }
- 16657 }
- 16660 /*===========================================================================*
- 16661 * get_work *
- 16662 *===========================================================================*/
- 16663 PRIVATE void get_work()
- 16664 {
- 16665 /* Wait for the next message and extract useful information from it. */
- 16666
- 16667 if (receive(ANY, &mm_in) != OK) panic("MM receive error", NO_NUM);
- 16668 who = mm_in.m_source; /* who sent the message */
- 16669 mm_call = mm_in.m_type; /* system call number */
- 16670 }
- 16673 /*===========================================================================*
- 16674 * reply *
- 16675 *===========================================================================*/
- 16676 PUBLIC void reply(proc_nr, result, res2, respt)
- 16677 int proc_nr; /* process to reply to */
- 16678 int result; /* result of the call (usually OK or error #)*/
- 16679 int res2; /* secondary result */
- 16680 char *respt; /* result if pointer */
- 16681 {
- 16682 /* Send a reply to a user process. */
- 16683
- 16684 register struct mproc *proc_ptr;
- 16685
- 16686 proc_ptr = &mproc[proc_nr];
- 16687 /*
- 16688 * To make MM robust, check to see if destination is still alive. This
- 16689 * validy check must be skipped if the caller is a task.
- 16690 */
- 16691 if ((who >=0) && ((proc_ptr->mp_flags&IN_USE) == 0 ||
- 16692 (proc_ptr->mp_flags&HANGING))) return;
- 16693
- 16694 reply_type = result;
- 16695 reply_i1 = res2;
- 16696 reply_p1 = respt;
- 16697 if (send(proc_nr, &mm_out) != OK) panic("MM can't reply", NO_NUM);
- 16698 }
- 16701 /*===========================================================================*
- 16702 * mm_init *
- 16703 *===========================================================================*/
- 16704 PRIVATE void mm_init()
- 16705 {
- 16706 /* Initialize the memory manager. */
- 16707
- 16708 static char core_sigs[] = {
- 16709 SIGQUIT, SIGILL, SIGTRAP, SIGABRT,
- 16710 SIGEMT, SIGFPE, SIGUSR1, SIGSEGV,
- 16711 SIGUSR2, 0 };
- 16712 register int proc_nr;
- 16713 register struct mproc *rmp;
- 16714 register char *sig_ptr;
- 16715 phys_clicks ram_clicks, total_clicks, minix_clicks, free_clicks, dummy;
- 16716 message mess;
- 16717 struct mem_map kernel_map[NR_SEGS];
- 16718 int mem;
- 16719
- 16720 /* Build the set of signals which cause core dumps. Do it the Posix
- 16721 * way, so no knowledge of bit positions is needed.
- 16722 */
- 16723 sigemptyset(&core_sset);
- 16724 for (sig_ptr = core_sigs; *sig_ptr != 0; sig_ptr++)
- 16725 sigaddset(&core_sset, *sig_ptr);
- 16726
- 16727 /* Get the memory map of the kernel to see how much memory it uses,
- 16728 * including the gap between address 0 and the start of the kernel.
- 16729 */
- 16730 sys_getmap(SYSTASK, kernel_map);
- 16731 minix_clicks = kernel_map[S].mem_phys + kernel_map[S].mem_len;
- 16732
- 16733 /* Initialize MM's tables. */
- 16734 for (proc_nr = 0; proc_nr <= INIT_PROC_NR; proc_nr++) {
- 16735 rmp = &mproc[proc_nr];
- 16736 rmp->mp_flags |= IN_USE;
- 16737 sys_getmap(proc_nr, rmp->mp_seg);
- 16738 if (rmp->mp_seg[T].mem_len != 0) rmp->mp_flags |= SEPARATE;
- 16739 minix_clicks += (rmp->mp_seg[S].mem_phys + rmp->mp_seg[S].mem_len)
- 16740 - rmp->mp_seg[T].mem_phys;
- 16741 }
- 16742 mproc[INIT_PROC_NR].mp_pid = INIT_PID;
- 16743 sigemptyset(&mproc[INIT_PROC_NR].mp_ignore);
- 16744 sigemptyset(&mproc[INIT_PROC_NR].mp_catch);
- 16745 procs_in_use = LOW_USER + 1;
- 16746
- 16747 /* Wait for FS to send a message telling the RAM disk size then go "on-line".
- 16748 */
- 16749 if (receive(FS_PROC_NR, &mess) != OK)
- 16750 panic("MM can't obtain RAM disk size from FS", NO_NUM);
- 16751
- 16752 ram_clicks = mess.m1_i1;
- 16753
- 16754 /* Initialize tables to all physical mem. */
- 16755 mem_init(&total_clicks, &free_clicks);
- 16756
- 16757 /* Print memory information. */
- 16758 printf("nMemory size =%5dK ", click_to_round_k(total_clicks));
- 16759 printf("MINIX =%4dK ", click_to_round_k(minix_clicks));
- 16760 printf("RAM disk =%5dK ", click_to_round_k(ram_clicks));
- 16761 printf("Available =%5dKnn", click_to_round_k(free_clicks));
- 16762
- 16763 /* Tell FS to continue. */
- 16764 if (send(FS_PROC_NR, &mess) != OK)
- 16765 panic("MM can't sync up with FS", NO_NUM);
- 16766
- 16767 /* Tell the memory task where my process table is for the sake of ps(1). */
- 16768 if ((mem = open("/dev/mem", O_RDWR)) != -1) {
- 16769 ioctl(mem, MIOCSPSINFO, (void *) mproc);
- 16770 close(mem);
- 16771 }
- 16772 }
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- src/mm/forkexit.c
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- 16800 /* This file deals with creating processes (via FORK) and deleting them (via
- 16801 * EXIT/WAIT). When a process forks, a new slot in the 'mproc' table is
- 16802 * allocated for it, and a copy of the parent's core image is made for the
- 16803 * child. Then the kernel and file system are informed. A process is removed
- 16804 * from the 'mproc' table when two events have occurred: (1) it has exited or
- 16805 * been killed by a signal, and (2) the parent has done a WAIT. If the process
- 16806 * exits first, it continues to occupy a slot until the parent does a WAIT.
- 16807 *
- 16808 * The entry points into this file are:
- 16809 * do_fork: perform the FORK system call
- 16810 * do_mm_exit: perform the EXIT system call (by calling mm_exit())
- 16811 * mm_exit: actually do the exiting
- 16812 * do_wait: perform the WAITPID or WAIT system call
- 16813 */
- 16814
- 16815
- 16816 #include "mm.h"
- 16817 #include <sys/wait.h>
- 16818 #include <minix/callnr.h>
- 16819 #include <signal.h>
- 16820 #include "mproc.h"
- 16821 #include "param.h"
- 16822
- 16823 #define LAST_FEW 2 /* last few slots reserved for superuser */
- 16824
- 16825 PRIVATE pid_t next_pid = INIT_PID+1; /* next pid to be assigned */
- 16826
- 16827 FORWARD _PROTOTYPE (void cleanup, (register struct mproc *child) );
- 16828
- 16829 /*===========================================================================*
- 16830 * do_fork *
- 16831 *===========================================================================*/
- 16832 PUBLIC int do_fork()
- 16833 {
- 16834 /* The process pointed to by 'mp' has forked. Create a child process. */
- 16835
- 16836 register struct mproc *rmp; /* pointer to parent */
- 16837 register struct mproc *rmc; /* pointer to child */
- 16838 int i, child_nr, t;
- 16839 phys_clicks prog_clicks, child_base = 0;
- 16840 phys_bytes prog_bytes, parent_abs, child_abs; /* Intel only */
- 16841
- 16842 /* If tables might fill up during FORK, don't even start since recovery half
- 16843 * way through is such a nuisance.
- 16844 */
- 16845 rmp = mp;
- 16846 if (procs_in_use == NR_PROCS) return(EAGAIN);
- 16847 if (procs_in_use >= NR_PROCS-LAST_FEW && rmp->mp_effuid != 0)return(EAGAIN);
- 16848
- 16849 /* Determine how much memory to allocate. Only the data and stack need to
- 16850 * be copied, because the text segment is either shared or of zero length.
- 16851 */
- 16852 prog_clicks = (phys_clicks) rmp->mp_seg[S].mem_len;
- 16853 prog_clicks += (rmp->mp_seg[S].mem_vir - rmp->mp_seg[D].mem_vir);
- 16854 prog_bytes = (phys_bytes) prog_clicks << CLICK_SHIFT;
- 16855 if ( (child_base = alloc_mem(prog_clicks)) == NO_MEM) return(EAGAIN);
- 16856
- 16857 /* Create a copy of the parent's core image for the child. */
- 16858 child_abs = (phys_bytes) child_base << CLICK_SHIFT;
- 16859 parent_abs = (phys_bytes) rmp->mp_seg[D].mem_phys << CLICK_SHIFT;
- 16860 i = sys_copy(ABS, 0, parent_abs, ABS, 0, child_abs, prog_bytes);
- 16861 if (i < 0) panic("do_fork can't copy", i);
- 16862
- 16863 /* Find a slot in 'mproc' for the child process. A slot must exist. */
- 16864 for (rmc = &mproc[0]; rmc < &mproc[NR_PROCS]; rmc++)
- 16865 if ( (rmc->mp_flags & IN_USE) == 0) break;
- 16866
- 16867 /* Set up the child and its memory map; copy its 'mproc' slot from parent. */
- 16868 child_nr = (int)(rmc - mproc); /* slot number of the child */
- 16869 procs_in_use++;
- 16870 *rmc = *rmp; /* copy parent's process slot to child's */
- 16871
- 16872 rmc->mp_parent = who; /* record child's parent */
- 16873 rmc->mp_flags &= ~TRACED; /* child does not inherit trace status */
- 16874 /* A separate I&D child keeps the parents text segment. The data and stack
- 16875 * segments must refer to the new copy.
- 16876 */
- 16877 if (!(rmc->mp_flags & SEPARATE)) rmc->mp_seg[T].mem_phys = child_base;
- 16878 rmc->mp_seg[D].mem_phys = child_base;
- 16879 rmc->mp_seg[S].mem_phys = rmc->mp_seg[D].mem_phys +
- 16880 (rmp->mp_seg[S].mem_vir - rmp->mp_seg[D].mem_vir);
- 16881 rmc->mp_exitstatus = 0;
- 16882 rmc->mp_sigstatus = 0;
- 16883
- 16884 /* Find a free pid for the child and put it in the table. */
- 16885 do {
- 16886 t = 0; /* 't' = 0 means pid still free */
- 16887 next_pid = (next_pid < 30000 ? next_pid + 1 : INIT_PID + 1);
- 16888 for (rmp = &mproc[0]; rmp < &mproc[NR_PROCS]; rmp++)
- 16889 if (rmp->mp_pid == next_pid || rmp->mp_procgrp == next_pid) {
- 16890 t = 1;
- 16891 break;
- 16892 }
- 16893 rmc->mp_pid = next_pid; /* assign pid to child */
- 16894 } while (t);
- 16895
- 16896 /* Tell kernel and file system about the (now successful) FORK. */
- 16897 sys_fork(who, child_nr, rmc->mp_pid, child_base); /* child_base is 68K only*/
- 16898 tell_fs(FORK, who, child_nr, rmc->mp_pid);
- 16899
- 16900 /* Report child's memory map to kernel. */
- 16901 sys_newmap(child_nr, rmc->mp_seg);
- 16902
- 16903 /* Reply to child to wake it up. */
- 16904 reply(child_nr, 0, 0, NIL_PTR);
- 16905 return(next_pid); /* child's pid */
- 16906 }
- 16909 /*===========================================================================*
- 16910 * do_mm_exit *
- 16911 *===========================================================================*/
- 16912 PUBLIC int do_mm_exit()
- 16913 {
- 16914 /* Perform the exit(status) system call. The real work is done by mm_exit(),
- 16915 * which is also called when a process is killed by a signal.
- 16916 */
- 16917
- 16918 mm_exit(mp, status);
- 16919 dont_reply = TRUE; /* don't reply to newly terminated process */
- 16920 return(OK); /* pro forma return code */
- 16921 }
- 16924 /*===========================================================================*
- 16925 * mm_exit *
- 16926 *===========================================================================*/
- 16927 PUBLIC void mm_exit(rmp, exit_status)
- 16928 register struct mproc *rmp; /* pointer to the process to be terminated */
- 16929 int exit_status; /* the process' exit status (for parent) */
- 16930 {
- 16931 /* A process is done. Release most of the process' possessions. If its
- 16932 * parent is waiting, release the rest, else hang.
- 16933 */
- 16934
- 16935 register int proc_nr;
- 16936 int parent_waiting, right_child;
- 16937 pid_t pidarg, procgrp;
- 16938 phys_clicks base, size, s; /* base and size used on 68000 only */
- 16939
- 16940 proc_nr = (int) (rmp - mproc); /* get process slot number */
- 16941
- 16942 /* Remember a session leader's process group. */
- 16943 procgrp = (rmp->mp_pid == mp->mp_procgrp) ? mp->mp_procgrp : 0;
- 16944
- 16945 /* If the exited process has a timer pending, kill it. */
- 16946 if (rmp->mp_flags & ALARM_ON) set_alarm(proc_nr, (unsigned) 0);
- 16947
- 16948 /* Tell the kernel and FS that the process is no longer runnable. */
- 16949 tell_fs(EXIT, proc_nr, 0, 0); /* file system can free the proc slot */
- 16950 sys_xit(rmp->mp_parent, proc_nr, &base, &size);
- 16951
- 16952 /* Release the memory occupied by the child. */
- 16953 if (find_share(rmp, rmp->mp_ino, rmp->mp_dev, rmp->mp_ctime) == NULL) {
- 16954 /* No other process shares the text segment, so free it. */
- 16955 free_mem(rmp->mp_seg[T].mem_phys, rmp->mp_seg[T].mem_len);
- 16956 }
- 16957 /* Free the data and stack segments. */
- 16958 free_mem(rmp->mp_seg[D].mem_phys,
- 16959 rmp->mp_seg[S].mem_vir + rmp->mp_seg[S].mem_len - rmp->mp_seg[D].mem_vir);
- 16960
- 16961 /* The process slot can only be freed if the parent has done a WAIT. */
- 16962 rmp->mp_exitstatus = (char) exit_status;
- 16963 pidarg = mproc[rmp->mp_parent].mp_wpid; /* who's being waited for? */
- 16964 parent_waiting = mproc[rmp->mp_parent].mp_flags & WAITING;
- 16965 if (pidarg == -1 || pidarg == rmp->mp_pid || -pidarg == rmp->mp_procgrp)
- 16966 right_child = TRUE; /* child meets one of the 3 tests */
- 16967 else
- 16968 right_child = FALSE; /* child fails all 3 tests */
- 16969 if (parent_waiting && right_child)
- 16970 cleanup(rmp); /* tell parent and release child slot */
- 16971 else
- 16972 rmp->mp_flags |= HANGING; /* parent not waiting, suspend child */
- 16973
- 16974 /* If the process has children, disinherit them. INIT is the new parent. */
- 16975 for (rmp = &mproc[0]; rmp < &mproc[NR_PROCS]; rmp++) {
- 16976 if (rmp->mp_flags & IN_USE && rmp->mp_parent == proc_nr) {
- 16977 /* 'rmp' now points to a child to be disinherited. */
- 16978 rmp->mp_parent = INIT_PROC_NR;
- 16979 parent_waiting = mproc[INIT_PROC_NR].mp_flags & WAITING;
- 16980 if (parent_waiting && (rmp->mp_flags & HANGING)) cleanup(rmp);
- 16981 }
- 16982 }
- 16983
- 16984 /* Send a hangup to the process' process group if it was a session leader. */
- 16985 if (procgrp != 0) check_sig(-procgrp, SIGHUP);
- 16986 }
- 16989 /*===========================================================================*
- 16990 * do_waitpid *
- 16991 *===========================================================================*/
- 16992 PUBLIC int do_waitpid()
- 16993 {
- 16994 /* A process wants to wait for a child to terminate. If one is already waiting,
- 16995 * go clean it up and let this WAIT call terminate. Otherwise, really wait.
- 16996 * Both WAIT and WAITPID are handled by this code.
- 16997 */
- 16998
- 16999 register struct mproc *rp;
- 17000 int pidarg, options, children, res2;
- 17001
- 17002 /* A process calling WAIT never gets a reply in the usual way via the
- 17003 * reply() in the main loop (unless WNOHANG is set or no qualifying child
- 17004 * exists). If a child has already exited, the routine cleanup() sends
- 17005 * the reply to awaken the caller.
- 17006 */
- 17007
- 17008 /* Set internal variables, depending on whether this is WAIT or WAITPID. */
- 17009 pidarg = (mm_call == WAIT ? -1 : pid); /* first param of waitpid */
- 17010 options = (mm_call == WAIT ? 0 : sig_nr); /* third param of waitpid */
- 17011 if (pidarg == 0) pidarg = -mp->mp_procgrp; /* pidarg < 0 ==> proc grp */
- 17012
- 17013 /* Is there a child waiting to be collected? At this point, pidarg != 0:
- 17014 * pidarg > 0 means pidarg is pid of a specific process to wait for
- 17015 * pidarg == -1 means wait for any child
- 17016 * pidarg < -1 means wait for any child whose process group = -pidarg
- 17017 */
- 17018 children = 0;
- 17019 for (rp = &mproc[0]; rp < &mproc[NR_PROCS]; rp++) {
- 17020 if ( (rp->mp_flags & IN_USE) && rp->mp_parent == who) {
- 17021 /* The value of pidarg determines which children qualify. */
- 17022 if (pidarg > 0 && pidarg != rp->mp_pid) continue;
- 17023 if (pidarg < -1 && -pidarg != rp->mp_procgrp) continue;
- 17024
- 17025 children++; /* this child is acceptable */
- 17026 if (rp->mp_flags & HANGING) {
- 17027 /* This child meets the pid test and has exited. */
- 17028 cleanup(rp); /* this child has already exited */
- 17029 dont_reply = TRUE;
- 17030 return(OK);
- 17031 }
- 17032 if ((rp->mp_flags & STOPPED) && rp->mp_sigstatus) {
- 17033 /* This child meets the pid test and is being traced.*/
- 17034 res2 = 0177 | (rp->mp_sigstatus << 8);
- 17035 reply(who, rp->mp_pid, res2, NIL_PTR);
- 17036 dont_reply = TRUE;
- 17037 rp->mp_sigstatus = 0;
- 17038 return(OK);
- 17039 }
- 17040 }
- 17041 }
- 17042
- 17043 /* No qualifying child has exited. Wait for one, unless none exists. */
- 17044 if (children > 0) {
- 17045 /* At least 1 child meets the pid test exists, but has not exited. */
- 17046 if (options & WNOHANG) return(0); /* parent does not want to wait */
- 17047 mp->mp_flags |= WAITING; /* parent wants to wait */
- 17048 mp->mp_wpid = (pid_t) pidarg; /* save pid for later */
- 17049 dont_reply = TRUE; /* do not reply now though */
- 17050 return(OK); /* yes - wait for one to exit */
- 17051 } else {
- 17052 /* No child even meets the pid test. Return error immediately. */
- 17053 return(ECHILD); /* no - parent has no children */
- 17054 }
- 17055 }
- 17058 /*===========================================================================*
- 17059 * cleanup *
- 17060 *===========================================================================*/
- 17061 PRIVATE void cleanup(child)
- 17062 register struct mproc *child; /* tells which process is exiting */
- 17063 {
- 17064 /* Finish off the exit of a process. The process has exited or been killed
- 17065 * by a signal, and its parent is waiting.
- 17066 */
- 17067
- 17068 int exitstatus;
- 17069
- 17070 /* Wake up the parent. */
- 17071 exitstatus = (child->mp_exitstatus << 8) | (child->mp_sigstatus & 0377);
- 17072 reply(child->mp_parent, child->mp_pid, exitstatus, NIL_PTR);
- 17073 mproc[child->mp_parent].mp_flags &= ~WAITING; /* parent no longer waiting */
- 17074
- 17075 /* Release the process table entry. */
- 17076 child->mp_flags = 0;
- 17077 procs_in_use--;
- 17078 }
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- src/mm/exec.c
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- 17100 /* This file handles the EXEC system call. It performs the work as follows:
- 17101 * - see if the permissions allow the file to be executed
- 17102 * - read the header and extract the sizes
- 17103 * - fetch the initial args and environment from the user space
- 17104 * - allocate the memory for the new process
- 17105 * - copy the initial stack from MM to the process
- 17106 * - read in the text and data segments and copy to the process
- 17107 * - take care of setuid and setgid bits
- 17108 * - fix up 'mproc' table
- 17109 * - tell kernel about EXEC
- 17110 * - save offset to initial argc (for ps)
- 17111 *
- 17112 * The entry points into this file are:
- 17113 * do_exec: perform the EXEC system call
- 17114 * find_share: find a process whose text segment can be shared
- 17115 */
- 17116
- 17117 #include "mm.h"
- 17118 #include <sys/stat.h>
- 17119 #include <minix/callnr.h>
- 17120 #include <a.out.h>
- 17121 #include <signal.h>
- 17122 #include <string.h>
- 17123 #include "mproc.h"
- 17124 #include "param.h"
- 17125
- 17126 FORWARD _PROTOTYPE( void load_seg, (int fd, int seg, vir_bytes seg_bytes) );
- 17127 FORWARD _PROTOTYPE( int new_mem, (struct mproc *sh_mp, vir_bytes text_bytes,
- 17128 vir_bytes data_bytes, vir_bytes bss_bytes,
- 17129 vir_bytes stk_bytes, phys_bytes tot_bytes) );
- 17130 FORWARD _PROTOTYPE( void patch_ptr, (char stack [ARG_MAX ], vir_bytes base) );
- 17131 FORWARD _PROTOTYPE( int read_header, (int fd, int *ft, vir_bytes *text_bytes,
- 17132 vir_bytes *data_bytes, vir_bytes *bss_bytes,
- 17133 phys_bytes *tot_bytes, long *sym_bytes, vir_clicks sc,
- 17134 vir_bytes *pc) );
- 17135
- 17136
- 17137 /*===========================================================================*
- 17138 * do_exec *
- 17139 *===========================================================================*/
- 17140 PUBLIC int do_exec()
- 17141 {
- 17142 /* Perform the execve(name, argv, envp) call. The user library builds a
- 17143 * complete stack image, including pointers, args, environ, etc. The stack
- 17144 * is copied to a buffer inside MM, and then to the new core image.
- 17145 */
- 17146
- 17147 register struct mproc *rmp;
- 17148 struct mproc *sh_mp;
- 17149 int m, r, fd, ft, sn;
- 17150 static char mbuf[ARG_MAX]; /* buffer for stack and zeroes */
- 17151 static char name_buf[PATH_MAX]; /* the name of the file to exec */
- 17152 char *new_sp, *basename;
- 17153 vir_bytes src, dst, text_bytes, data_bytes, bss_bytes, stk_bytes, vsp;
- 17154 phys_bytes tot_bytes; /* total space for program, including gap */
- 17155 long sym_bytes;
- 17156 vir_clicks sc;
- 17157 struct stat s_buf;
- 17158 vir_bytes pc;
- 17159
- 17160 /* Do some validity checks. */
- 17161 rmp = mp;
- 17162 stk_bytes = (vir_bytes) stack_bytes;
- 17163 if (stk_bytes > ARG_MAX) return(ENOMEM); /* stack too big */
- 17164 if (exec_len <= 0 || exec_len > PATH_MAX) return(EINVAL);
- 17165
- 17166 /* Get the exec file name and see if the file is executable. */
- 17167 src = (vir_bytes) exec_name;
- 17168 dst = (vir_bytes) name_buf;
- 17169 r = sys_copy(who, D, (phys_bytes) src,
- 17170 MM_PROC_NR, D, (phys_bytes) dst, (phys_bytes) exec_len);
- 17171 if (r != OK) return(r); /* file name not in user data segment */
- 17172 tell_fs(CHDIR, who, FALSE, 0); /* switch to the user's FS environ. */
- 17173 fd = allowed(name_buf, &s_buf, X_BIT); /* is file executable? */
- 17174 if (fd < 0) return(fd); /* file was not executable */
- 17175
- 17176 /* Read the file header and extract the segment sizes. */
- 17177 sc = (stk_bytes + CLICK_SIZE - 1) >> CLICK_SHIFT;
- 17178 m = read_header(fd, &ft, &text_bytes, &data_bytes, &bss_bytes,
- 17179 &tot_bytes, &sym_bytes, sc, &pc);
- 17180 if (m < 0) {
- 17181 close(fd); /* something wrong with header */
- 17182 return(ENOEXEC);
- 17183 }
- 17184
- 17185 /* Fetch the stack from the user before destroying the old core image. */
- 17186 src = (vir_bytes) stack_ptr;
- 17187 dst = (vir_bytes) mbuf;
- 17188 r = sys_copy(who, D, (phys_bytes) src,
- 17189 MM_PROC_NR, D, (phys_bytes) dst, (phys_bytes)stk_bytes);
- 17190 if (r != OK) {
- 17191 close(fd); /* can't fetch stack (e.g. bad virtual addr) */
- 17192 return(EACCES);
- 17193 }
- 17194
- 17195 /* Can the process' text be shared with that of one already running? */
- 17196 sh_mp = find_share(rmp, s_buf.st_ino, s_buf.st_dev, s_buf.st_ctime);
- 17197
- 17198 /* Allocate new memory and release old memory. Fix map and tell kernel. */
- 17199 r = new_mem(sh_mp, text_bytes, data_bytes, bss_bytes, stk_bytes, tot_bytes);
- 17200 if (r != OK) {
- 17201 close(fd); /* insufficient core or program too big */
- 17202 return(r);
- 17203 }
- 17204
- 17205 /* Save file identification to allow it to be shared. */
- 17206 rmp->mp_ino = s_buf.st_ino;
- 17207 rmp->mp_dev = s_buf.st_dev;
- 17208 rmp->mp_ctime = s_buf.st_ctime;
- 17209
- 17210 /* Patch up stack and copy it from MM to new core image. */
- 17211 vsp = (vir_bytes) rmp->mp_seg[S].mem_vir << CLICK_SHIFT;
- 17212 vsp += (vir_bytes) rmp->mp_seg[S].mem_len << CLICK_SHIFT;
- 17213 vsp -= stk_bytes;
- 17214 patch_ptr(mbuf, vsp);
- 17215 src = (vir_bytes) mbuf;
- 17216 r = sys_copy(MM_PROC_NR, D, (phys_bytes) src,
- 17217 who, D, (phys_bytes) vsp, (phys_bytes)stk_bytes);
- 17218 if (r != OK) panic("do_exec stack copy err", NO_NUM);
- 17219
- 17220 /* Read in text and data segments. */
- 17221 if (sh_mp != NULL) {
- 17222 lseek(fd, (off_t) text_bytes, SEEK_CUR); /* shared: skip text */
- 17223 } else {
- 17224 load_seg(fd, T, text_bytes);
- 17225 }
- 17226 load_seg(fd, D, data_bytes);
- 17227
- 17228
- 17229 close(fd); /* don't need exec file any more */
- 17230
- 17231 /* Take care of setuid/setgid bits. */
- 17232 if ((rmp->mp_flags & TRACED) == 0) { /* suppress if tracing */
- 17233 if (s_buf.st_mode & I_SET_UID_BIT) {
- 17234 rmp->mp_effuid = s_buf.st_uid;
- 17235 tell_fs(SETUID,who, (int)rmp->mp_realuid, (int)rmp->mp_effuid);
- 17236 }
- 17237 if (s_buf.st_mode & I_SET_GID_BIT) {
- 17238 rmp->mp_effgid = s_buf.st_gid;
- 17239 tell_fs(SETGID,who, (int)rmp->mp_realgid, (int)rmp->mp_effgid);
- 17240 }
- 17241 }
- 17242
- 17243 /* Save offset to initial argc (for ps) */
- 17244 rmp->mp_procargs = vsp;
- 17245
- 17246 /* Fix 'mproc' fields, tell kernel that exec is done, reset caught sigs. */
- 17247 for (sn = 1; sn <= _NSIG; sn++) {
- 17248 if (sigismember(&rmp->mp_catch, sn)) {
- 17249 sigdelset(&rmp->mp_catch, sn);
- 17250 rmp->mp_sigact[sn].sa_handler = SIG_DFL;
- 17251 sigemptyset(&rmp->mp_sigact[sn].sa_mask);
- 17252 }
- 17253 }
- 17254
- 17255 rmp->mp_flags &= ~SEPARATE; /* turn off SEPARATE bit */
- 17256 rmp->mp_flags |= ft; /* turn it on for separate I & D files */
- 17257 new_sp = (char *) vsp;
- 17258
- 17259 tell_fs(EXEC, who, 0, 0); /* allow FS to handle FD_CLOEXEC files */
- 17260
- 17261 /* System will save command line for debugging, ps(1) output, etc. */
- 17262 basename = strrchr(name_buf, '/');
- 17263 if (basename == NULL) basename = name_buf; else basename++;