/** * <Ring 1> Main loop of task TTY. *****************************************************************************/ PUBLIC void task_tty() { TTY * tty; MESSAGE msg; init_keyboard(); for (tty = TTY_FIRST; tty < TTY_END; tty++) init_tty(tty); select_console(0); while (1) { for (tty = TTY_FIRST; tty < TTY_END; tty++) { do { tty_dev_read(tty); tty_dev_write(tty); } while (tty->ibuf_cnt); } send_recv(RECEIVE, ANY, &msg); int src = msg.source; assert(src != TASK_TTY); TTY* ptty = &tty_table[msg.DEVICE]; switch (msg.type) { case DEV_OPEN: reset_msg(&msg); msg.type = SYSCALL_RET; send_recv(SEND, src, &msg); break; case DEV_READ: tty_do_read(ptty, &msg); break; case DEV_WRITE: tty_do_write(ptty, &msg); break; case HARD_INT: /** * waked up by clock_handler -- a key was just pressed * @see clock_handler() inform_int() */ key_pressed = 0; continue; default: dump_msg("TTY::unknown msg", &msg); break; } } }
/** * Main loop of HD driver. * *****************************************************************************/ PUBLIC void task_hd() { MESSAGE msg; //init_dma(); init_hd(); while (1) { reset_msg(&msg); send_recv(RECEIVE, ANY, &msg); int src = msg.source; switch (msg.type) { case DEV_OPEN: hd_open(msg.DEVICE); break; case DEV_CLOSE: hd_close(msg.DEVICE); break; case DEV_READ: case DEV_WRITE: hd_rdwt(&msg); break; case DEV_IOCTL: hd_ioctl(&msg); break; case DEV_DMA: break; default: dump_msg("HD driver::unknown msg", &msg); spin("FS::main_loop (invalid msg.type)"); break; } send_recv(SEND, src, &msg); } }
PUBLIC void task_clock() { MESSAGE m; int result; while(TRUE) { reset_msg(&m); send_recv(RECEIVE,ANY,&m); switch(m.type) { case HARD_INT: result=do_clockclick(); break; default: printf("CLOCK: illegal request from ...%d",m.source); } } }
/** * <Ring 0> Try to get a message from the src proc. If src is blocked sending * the message, copy the message from it and unblock src. Otherwise the caller * will be blocked. * * @param current The caller, the proc who wanna receive. * @param src From whom the message will be received. * @param m The message ptr to accept the message. * * @return Zero if success. *****************************************************************************/ PRIVATE int msg_receive(struct proc* current, int src, MESSAGE* m) { struct proc* p_who_wanna_recv = current; /** * This name is a little bit * wierd, but it makes me * think clearly, so I keep * it. */ struct proc* p_from = 0; /* from which the message will be fetched */ struct proc* prev = 0; int copyok = 0; assert(proc2pid(p_who_wanna_recv) != src); if ((p_who_wanna_recv->has_int_msg) && ((src == ANY) || (src == INTERRUPT))) { /* There is an interrupt needs p_who_wanna_recv's handling and * p_who_wanna_recv is ready to handle it. */ MESSAGE msg; reset_msg(&msg); msg.source = INTERRUPT; msg.type = HARD_INT; assert(m); phys_copy(va2la(proc2pid(p_who_wanna_recv), m), &msg, sizeof(MESSAGE)); p_who_wanna_recv->has_int_msg = 0; assert(p_who_wanna_recv->p_flags == 0); assert(p_who_wanna_recv->p_msg == 0); assert(p_who_wanna_recv->p_sendto == NO_TASK); assert(p_who_wanna_recv->has_int_msg == 0); return 0; } /* Arrives here if no interrupt for p_who_wanna_recv. */ if (src == ANY) { /* p_who_wanna_recv is ready to receive messages from * ANY proc, we'll check the sending queue and pick the * first proc in it. */ if (p_who_wanna_recv->q_sending) { p_from = p_who_wanna_recv->q_sending; copyok = 1; assert(p_who_wanna_recv->p_flags == 0); assert(p_who_wanna_recv->p_msg == 0); assert(p_who_wanna_recv->p_recvfrom == NO_TASK); assert(p_who_wanna_recv->p_sendto == NO_TASK); assert(p_who_wanna_recv->q_sending != 0); assert(p_from->p_flags == SENDING); assert(p_from->p_msg != 0); assert(p_from->p_recvfrom == NO_TASK); assert(p_from->p_sendto == proc2pid(p_who_wanna_recv)); } } else { /* p_who_wanna_recv wants to receive a message from * a certain proc: src. */ p_from = &proc_table[src]; if ((p_from->p_flags & SENDING) && (p_from->p_sendto == proc2pid(p_who_wanna_recv))) { /* Perfect, src is sending a message to * p_who_wanna_recv. */ copyok = 1; struct proc* p = p_who_wanna_recv->q_sending; assert(p); /* p_from must have been appended to the * queue, so the queue must not be NULL */ while (p) { assert(p_from->p_flags & SENDING); if (proc2pid(p) == src) { /* if p is the one */ p_from = p; break; } prev = p; p = p->next_sending; } assert(p_who_wanna_recv->p_flags == 0); assert(p_who_wanna_recv->p_msg == 0); assert(p_who_wanna_recv->p_recvfrom == NO_TASK); assert(p_who_wanna_recv->p_sendto == NO_TASK); assert(p_who_wanna_recv->q_sending != 0); assert(p_from->p_flags == SENDING); assert(p_from->p_msg != 0); assert(p_from->p_recvfrom == NO_TASK); assert(p_from->p_sendto == proc2pid(p_who_wanna_recv)); } } if (copyok) { /* It's determined from which proc the message will * be copied. Note that this proc must have been * waiting for this moment in the queue, so we should * remove it from the queue. */ if (p_from == p_who_wanna_recv->q_sending) { /* the 1st one */ assert(prev == 0); p_who_wanna_recv->q_sending = p_from->next_sending; p_from->next_sending = 0; } else { assert(prev); prev->next_sending = p_from->next_sending; p_from->next_sending = 0; } assert(m); assert(p_from->p_msg); /* copy the message */ phys_copy(va2la(proc2pid(p_who_wanna_recv), m), va2la(proc2pid(p_from), p_from->p_msg), sizeof(MESSAGE)); p_from->p_msg = 0; p_from->p_sendto = NO_TASK; p_from->p_flags &= ~SENDING; unblock(p_from); } else { /* nobody's sending any msg */ /* Set p_flags so that p_who_wanna_recv will not * be scheduled until it is unblocked. */ p_who_wanna_recv->p_flags |= RECEIVING; p_who_wanna_recv->p_msg = m; if (src == ANY) p_who_wanna_recv->p_recvfrom = ANY; else p_who_wanna_recv->p_recvfrom = proc2pid(p_from); block(p_who_wanna_recv); assert(p_who_wanna_recv->p_flags == RECEIVING); assert(p_who_wanna_recv->p_msg != 0); assert(p_who_wanna_recv->p_recvfrom != NO_TASK); assert(p_who_wanna_recv->p_sendto == NO_TASK); assert(p_who_wanna_recv->has_int_msg == 0); } return 0; }
/************************************************************************************************** * msg_receive ************************************************************************************************** * <Ring 0> Try to get a message from the src proc. * If src is blocked sending the message, copy the message from it and unblock src. * Otherwise the caller will be blocked. * * @param current The caller, the proc who wanna receive. * @param src From whom the message will be received. * @param m Pointer to the MESSAGE struct. * * @return 0 if success. *************************************************************************************************/ PRIVATE int msg_receive(PROCESS* current, int src, MESSAGE* m){ PROCESS* p_who_wanna_recv = current; PROCESS* p_from = 0; PROCESS* prev = 0; /* the prior of p_from in the sending queue. */ int copyok = FALSE; assert(proc2pid(p_who_wanna_recv) != src); /* * There is an interrupt needs p_who_wanna_recv's handling and p_who_wanna_recv is ready * to handle it. */ if((p_who_wanna_recv->has_int_msg) && ((src == ANY) || (src == INTERRUPT))){ MESSAGE msg; reset_msg(&msg); msg.source = INTERRUPT; msg.type = HARD_INT; assert(m); phys_copy(va2la(proc2pid(p_who_wanna_recv), m), &msg, sizeof(MESSAGE)); p_who_wanna_recv->has_int_msg = 0; assert(p_who_wanna_recv->flags == 0); assert(p_who_wanna_recv->p_msg == 0); assert(p_who_wanna_recv->send_to == NO_TASK); assert(p_who_wanna_recv->has_int_msg == 0); return 0; } /* * Arrive here if no interrupt for p_who_wanna_recv. * * p_who_wanna_recv is ready to receive messages from ANY proc, we'll check the sending queue * and pick the first proc in it. */ if(src == ANY){ if(p_who_wanna_recv->q_sending){ p_from = p_who_wanna_recv->q_sending; copyok = TRUE; assert(p_who_wanna_recv->flags == 0); assert(p_who_wanna_recv->p_msg == 0); assert(p_who_wanna_recv->recv_from == NO_TASK); assert(p_who_wanna_recv->send_to == NO_TASK); assert(p_who_wanna_recv->q_sending != 0); assert(p_from->flags == SENDING); assert(p_from->p_msg != 0); assert(p_from->recv_from == NO_TASK); assert(p_from->send_to == proc2pid(p_who_wanna_recv)); } }else{/* p_who_wanna_recv wants to receive a message from a certain proc: src. */ p_from = &proc_table[src]; if((p_from->flags & SENDING) && (p_from->send_to == proc2pid(p_who_wanna_recv))){ copyok = TRUE; PROCESS* p = p_who_wanna_recv->q_sending; assert(p); /* p_from must have been appended to the queue */ while(p){ assert(p_from->flags & SENDING); if(proc2pid(p) == src){ p_from = p; break; } prev = p; p = p->next_sending; } assert(p_who_wanna_recv->flags == 0); assert(p_who_wanna_recv->p_msg == 0); assert(p_who_wanna_recv->recv_from == NO_TASK); assert(p_who_wanna_recv->send_to == NO_TASK); assert(p_who_wanna_recv->q_sending != 0); assert(p_from->flags == SENDING); assert(p_from->p_msg != 0); assert(p_from->recv_from == NO_TASK); assert(p_from->send_to == proc2pid(p_who_wanna_recv)); } } /* * It's determined from which proc the message will be copied. * Note that this proc must have been waiting for this moment in the queue, * so we should remove it from the queue. */ if(copyok){ if(p_from == p_who_wanna_recv->q_sending){ /* the 1st one. */ assert(prev == 0); p_who_wanna_recv->q_sending = p_from->next_sending; p_from->next_sending = 0; }else{ assert(prev); prev->next_sending = p_from->next_sending; p_from->next_sending = 0; } assert(m); assert(p_from->p_msg); /* It's time to copy the message. */ phys_copy(va2la(proc2pid(p_who_wanna_recv), m), va2la(proc2pid(p_from), p_from->p_msg), sizeof(MESSAGE)); p_from->p_msg = 0; p_from->send_to = NO_TASK; p_from->flags &= ~SENDING; unblock(p_from); } /* * Unfortunately, nobody is sending any message. * Set flags so that p_who_wanna_recv will not be shceduled util it is unblocked. */ else{ p_who_wanna_recv->flags |= RECEIVING; p_who_wanna_recv->p_msg = m; if(src == ANY){ p_who_wanna_recv->recv_from = ANY; }else{ p_who_wanna_recv->recv_from = proc2pid(p_from); } block(p_who_wanna_recv); assert(p_who_wanna_recv->flags == RECEIVING); assert(p_who_wanna_recv->p_msg != 0); assert(p_who_wanna_recv->recv_from != NO_TASK); assert(p_who_wanna_recv->send_to == NO_TASK); assert(p_who_wanna_recv->has_int_msg == 0); } return 0; }
PRIVATE int msg_receive(PROCESS *current, int src, MESSAGE *m) { PROCESS *p_who_wanna_recv = current; PROCESS *p_from = 0; PROCESS *prev = 0; int copyok = 0; assert(proc2pid(p_who_wanna_recv) != src); // 不能自己接收自己的消息 if ((p_who_wanna_recv->has_int_msg) && ((src == ANY) || (src == INTERRUPT))) { MESSAGE msg; reset_msg(&msg); msg.source = INTERRUPT; msg.type = HARD_INT; assert(m); phys_copy(va2la(proc2pid(p_who_wanna_recv), m), &msg, sizeof(MESSAGE)); p_who_wanna_recv->has_int_msg = FALSE; assert(p_who_wanna_recv->p_flags == 0); assert(p_who_wanna_recv->p_msg == 0); assert(p_who_wanna_recv->p_sendto == NO_TASK); assert(p_who_wanna_recv->q_sending == 0); return 0; } if (src == ANY) { // 如果要等待来自任何进程的消息 if (p_who_wanna_recv->q_sending) { // 如果消息队列不为空 p_from = p_who_wanna_recv->q_sending; // 取消息队列中第一个 copyok = TRUE; assert(p_who_wanna_recv->p_flags == 0); assert(p_who_wanna_recv->p_msg == 0); assert(p_who_wanna_recv->p_recvfrom == NO_TASK); assert(p_who_wanna_recv->p_sendto == NO_TASK); assert(p_who_wanna_recv->q_sending != 0); assert(p_from->p_flags == SENDING); assert(p_from->p_msg != 0); assert(p_from->p_recvfrom == NO_TASK); assert(p_from->p_sendto == proc2pid(p_who_wanna_recv)); } } else { // 如果要等待指定进程的消息 p_from = &proc_table[src]; if ((p_from->p_flags & SENDING) && // 如果指定的进程正在发送消息 (p_from->p_sendto == proc2pid(p_who_wanna_recv))) { // 并且就是发送给该进程 copyok = TRUE; PROCESS *p = p_who_wanna_recv->q_sending; assert(p); /* 在消息队列中找到指定的进程 */ while (p) { assert(p_from->p_flags & SENDING); if (proc2pid(p) == src) { p_from = p; break; } prev = p; p = p->next_sending; } assert(p_who_wanna_recv->p_flags == 0); assert(p_who_wanna_recv->p_msg == 0); assert(p_who_wanna_recv->p_recvfrom == NO_TASK); assert(p_who_wanna_recv->p_sendto == NO_TASK); assert(p_who_wanna_recv->q_sending != 0); assert(p_from->p_flags == SENDING); assert(p_from->p_msg != 0); assert(p_from->p_recvfrom == NO_TASK); assert(p_from->p_sendto == proc2pid(p_who_wanna_recv)); } } if (copyok) { // 如果成功接收到了消息 if (p_from == p_who_wanna_recv->q_sending) { assert(prev == 0); p_who_wanna_recv->q_sending = p_from->next_sending; p_from->next_sending = 0; } else { assert(prev); prev->next_sending = p_from->next_sending; p_from->next_sending = 0; } assert(m); assert(p_from->p_msg); phys_copy(va2la(proc2pid(p_who_wanna_recv), m), va2la(proc2pid(p_from), p_from->p_msg), sizeof(MESSAGE)); p_from->p_msg = 0; p_from->p_sendto = NO_TASK; p_from->p_flags &= ~SENDING; unblock(p_from); // 恢复发送者 } else { p_who_wanna_recv->p_flags |= RECEIVING; p_who_wanna_recv->p_msg = m; p_who_wanna_recv->p_recvfrom = src == ANY ? ANY : proc2pid(p_from); block(p_who_wanna_recv); // 挂起 assert(p_who_wanna_recv->p_flags == RECEIVING); assert(p_who_wanna_recv->p_msg != 0); assert(p_who_wanna_recv->p_recvfrom != NO_TASK); assert(p_who_wanna_recv->p_sendto == NO_TASK); assert(p_who_wanna_recv->has_int_msg == 0); } return 0; }