proc.c
Upload User: mufangfei
Upload Date: 2019-10-27
Package Size: 17362k
Code Size: 19k
Category:

Oracle

Development Platform:

Unix_Linux

  1. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2.                                proc.c
  3. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  4.                                                     Forrest Yu, 2005
  5. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
  6. #include "type.h"
  7. #include "stdio.h"
  8. #include "const.h"
  9. #include "protect.h"
  10. #include "tty.h"
  11. #include "console.h"
  12. #include "string.h"
  13. #include "fs.h"
  14. #include "proc.h"
  15. #include "global.h"
  16. #include "proto.h"
  17. PRIVATE void block(struct proc* p);
  18. PRIVATE void unblock(struct proc* p);
  19. PRIVATE int  msg_send(struct proc* current, int dest, MESSAGE* m);
  20. PRIVATE int  msg_receive(struct proc* current, int src, MESSAGE* m);
  21. PRIVATE int  deadlock(int src, int dest);
  22. /*****************************************************************************
  23.  *                                schedule
  24.  *****************************************************************************/
  25. /**
  26.  * <Ring 0> Choose one proc to run.
  27.  * 
  28.  *****************************************************************************/
  29. PUBLIC void schedule()
  30. {
  31. struct proc* p;
  32. int greatest_ticks = 0;
  33. while (!greatest_ticks) {
  34. for (p = &FIRST_PROC; p <= &LAST_PROC; p++) {
  35. if (p->p_flags == 0) {
  36. if (p->ticks > greatest_ticks) {
  37. greatest_ticks = p->ticks;
  38. p_proc_ready = p;
  39. }
  40. }
  41. }
  42. if (!greatest_ticks)
  43. for (p = &FIRST_PROC; p <= &LAST_PROC; p++)
  44. if (p->p_flags == 0)
  45. p->ticks = p->priority;
  46. }
  47. }
  48. /*****************************************************************************
  49.  *                                sys_sendrec
  50.  *****************************************************************************/
  51. /**
  52.  * <Ring 0> The core routine of system call `sendrec()'.
  53.  * 
  54.  * @param function SEND or RECEIVE
  55.  * @param src_dest To/From whom the message is transferred.
  56.  * @param m        Ptr to the MESSAGE body.
  57.  * @param p        The caller proc.
  58.  * 
  59.  * @return Zero if success.
  60.  *****************************************************************************/
  61. PUBLIC int sys_sendrec(int function, int src_dest, MESSAGE* m, struct proc* p)
  62. {
  63. assert(k_reenter == 0); /* make sure we are not in ring0 */
  64. assert((src_dest >= 0 && src_dest < NR_TASKS + NR_PROCS) ||
  65.        src_dest == ANY ||
  66.        src_dest == INTERRUPT);
  67. int ret = 0;
  68. int caller = proc2pid(p);
  69. MESSAGE* mla = (MESSAGE*)va2la(caller, m);
  70. mla->source = caller;
  71. assert(mla->source != src_dest);
  72. /**
  73.  * Actually we have the third message type: BOTH. However, it is not
  74.  * allowed to be passed to the kernel directly. Kernel doesn't know
  75.  * it at all. It is transformed into a SEND followed by a RECEIVE
  76.  * by `send_recv()'.
  77.  */
  78. if (function == SEND) {
  79. ret = msg_send(p, src_dest, m);
  80. if (ret != 0)
  81. return ret;
  82. }
  83. else if (function == RECEIVE) {
  84. ret = msg_receive(p, src_dest, m);
  85. if (ret != 0)
  86. return ret;
  87. }
  88. else {
  89. panic("{sys_sendrec} invalid function: "
  90.       "%d (SEND:%d, RECEIVE:%d).", function, SEND, RECEIVE);
  91. }
  92. return 0;
  93. }
  94. /*****************************************************************************
  95.  *                                send_recv
  96.  *****************************************************************************/
  97. /**
  98.  * <Ring 1~3> IPC syscall.
  99.  *
  100.  * It is an encapsulation of `sendrec',
  101.  * invoking `sendrec' directly should be avoided
  102.  *
  103.  * @param function  SEND, RECEIVE or BOTH
  104.  * @param src_dest  The caller's proc_nr
  105.  * @param msg       Pointer to the MESSAGE struct
  106.  * 
  107.  * @return always 0.
  108.  *****************************************************************************/
  109. PUBLIC int send_recv(int function, int src_dest, MESSAGE* msg)
  110. {
  111. int ret = 0;
  112. if (function == RECEIVE)
  113. memset(msg, 0, sizeof(MESSAGE));
  114. switch (function) {
  115. case BOTH:
  116. ret = sendrec(SEND, src_dest, msg);
  117. if (ret == 0)
  118. ret = sendrec(RECEIVE, src_dest, msg);
  119. break;
  120. case SEND:
  121. case RECEIVE:
  122. ret = sendrec(function, src_dest, msg);
  123. break;
  124. default:
  125. assert((function == BOTH) ||
  126.        (function == SEND) || (function == RECEIVE));
  127. break;
  128. }
  129. return ret;
  130. }
  131. /*****************************************************************************
  132.  *   ldt_seg_linear
  133.  *****************************************************************************/
  134. /**
  135.  * <Ring 0~1> Calculate the linear address of a certain segment of a given
  136.  * proc.
  137.  * 
  138.  * @param p   Whose (the proc ptr).
  139.  * @param idx Which (one proc has more than one segments).
  140.  * 
  141.  * @return  The required linear address.
  142.  *****************************************************************************/
  143. PUBLIC int ldt_seg_linear(struct proc* p, int idx)
  144. {
  145. struct descriptor * d = &p->ldts[idx];
  146. return d->base_high << 24 | d->base_mid << 16 | d->base_low;
  147. }
  148. /*****************************************************************************
  149.  *   va2la
  150.  *****************************************************************************/
  151. /**
  152.  * <Ring 0~1> Virtual addr --> Linear addr.
  153.  * 
  154.  * @param pid  PID of the proc whose address is to be calculated.
  155.  * @param va   Virtual address.
  156.  * 
  157.  * @return The linear address for the given virtual address.
  158.  *****************************************************************************/
  159. PUBLIC void* va2la(int pid, void* va)
  160. {
  161. struct proc* p = &proc_table[pid];
  162. u32 seg_base = ldt_seg_linear(p, INDEX_LDT_RW);
  163. u32 la = seg_base + (u32)va;
  164. if (pid < NR_TASKS + NR_PROCS) {
  165. assert(la == (u32)va);
  166. }
  167. return (void*)la;
  168. }
  169. /*****************************************************************************
  170.  *                                reset_msg
  171.  *****************************************************************************/
  172. /**
  173.  * <Ring 0~3> Clear up a MESSAGE by setting each byte to 0.
  174.  * 
  175.  * @param p  The message to be cleared.
  176.  *****************************************************************************/
  177. PUBLIC void reset_msg(MESSAGE* p)
  178. {
  179. memset(p, 0, sizeof(MESSAGE));
  180. }
  181. /*****************************************************************************
  182.  *                                block
  183.  *****************************************************************************/
  184. /**
  185.  * <Ring 0> This routine is called after `p_flags' has been set (!= 0), it
  186.  * calls `schedule()' to choose another proc as the `proc_ready'.
  187.  *
  188.  * @attention This routine does not change `p_flags'. Make sure the `p_flags'
  189.  * of the proc to be blocked has been set properly.
  190.  * 
  191.  * @param p The proc to be blocked.
  192.  *****************************************************************************/
  193. PRIVATE void block(struct proc* p)
  194. {
  195. assert(p->p_flags);
  196. schedule();
  197. }
  198. /*****************************************************************************
  199.  *                                unblock
  200.  *****************************************************************************/
  201. /**
  202.  * <Ring 0> This is a dummy routine. It does nothing actually. When it is
  203.  * called, the `p_flags' should have been cleared (== 0).
  204.  * 
  205.  * @param p The unblocked proc.
  206.  *****************************************************************************/
  207. PRIVATE void unblock(struct proc* p)
  208. {
  209. assert(p->p_flags == 0);
  210. }
  211. /*****************************************************************************
  212.  *                                deadlock
  213.  *****************************************************************************/
  214. /**
  215.  * <Ring 0> Check whether it is safe to send a message from src to dest.
  216.  * The routine will detect if the messaging graph contains a cycle. For
  217.  * instance, if we have procs trying to send messages like this:
  218.  * A -> B -> C -> A, then a deadlock occurs, because all of them will
  219.  * wait forever. If no cycles detected, it is considered as safe.
  220.  * 
  221.  * @param src   Who wants to send message.
  222.  * @param dest  To whom the message is sent.
  223.  * 
  224.  * @return Zero if success.
  225.  *****************************************************************************/
  226. PRIVATE int deadlock(int src, int dest)
  227. {
  228. struct proc* p = proc_table + dest;
  229. while (1) {
  230. if (p->p_flags & SENDING) {
  231. if (p->p_sendto == src) {
  232. /* print the chain */
  233. p = proc_table + dest;
  234. printl("=_=%s", p->name);
  235. do {
  236. assert(p->p_msg);
  237. p = proc_table + p->p_sendto;
  238. printl("->%s", p->name);
  239. } while (p != proc_table + src);
  240. printl("=_=");
  241. return 1;
  242. }
  243. p = proc_table + p->p_sendto;
  244. }
  245. else {
  246. break;
  247. }
  248. }
  249. return 0;
  250. }
  251. /*****************************************************************************
  252.  *                                msg_send
  253.  *****************************************************************************/
  254. /**
  255.  * <Ring 0> Send a message to the dest proc. If dest is blocked waiting for
  256.  * the message, copy the message to it and unblock dest. Otherwise the caller
  257.  * will be blocked and appended to the dest's sending queue.
  258.  * 
  259.  * @param current  The caller, the sender.
  260.  * @param dest     To whom the message is sent.
  261.  * @param m        The message.
  262.  * 
  263.  * @return Zero if success.
  264.  *****************************************************************************/
  265. PRIVATE int msg_send(struct proc* current, int dest, MESSAGE* m)
  266. {
  267. struct proc* sender = current;
  268. struct proc* p_dest = proc_table + dest; /* proc dest */
  269. assert(proc2pid(sender) != dest);
  270. /* check for deadlock here */
  271. if (deadlock(proc2pid(sender), dest)) {
  272. panic(">>DEADLOCK<< %s->%s", sender->name, p_dest->name);
  273. }
  274. if ((p_dest->p_flags & RECEIVING) && /* dest is waiting for the msg */
  275.     (p_dest->p_recvfrom == proc2pid(sender) ||
  276.      p_dest->p_recvfrom == ANY)) {
  277. assert(p_dest->p_msg);
  278. assert(m);
  279. phys_copy(va2la(dest, p_dest->p_msg),
  280.   va2la(proc2pid(sender), m),
  281.   sizeof(MESSAGE));
  282. p_dest->p_msg = 0;
  283. p_dest->p_flags &= ~RECEIVING; /* dest has received the msg */
  284. p_dest->p_recvfrom = NO_TASK;
  285. unblock(p_dest);
  286. assert(p_dest->p_flags == 0);
  287. assert(p_dest->p_msg == 0);
  288. assert(p_dest->p_recvfrom == NO_TASK);
  289. assert(p_dest->p_sendto == NO_TASK);
  290. assert(sender->p_flags == 0);
  291. assert(sender->p_msg == 0);
  292. assert(sender->p_recvfrom == NO_TASK);
  293. assert(sender->p_sendto == NO_TASK);
  294. }
  295. else { /* dest is not waiting for the msg */
  296. sender->p_flags |= SENDING;
  297. assert(sender->p_flags == SENDING);
  298. sender->p_sendto = dest;
  299. sender->p_msg = m;
  300. /* append to the sending queue */
  301. struct proc * p;
  302. if (p_dest->q_sending) {
  303. p = p_dest->q_sending;
  304. while (p->next_sending)
  305. p = p->next_sending;
  306. p->next_sending = sender;
  307. }
  308. else {
  309. p_dest->q_sending = sender;
  310. }
  311. sender->next_sending = 0;
  312. block(sender);
  313. assert(sender->p_flags == SENDING);
  314. assert(sender->p_msg != 0);
  315. assert(sender->p_recvfrom == NO_TASK);
  316. assert(sender->p_sendto == dest);
  317. }
  318. return 0;
  319. }
  320. /*****************************************************************************
  321.  *                                msg_receive
  322.  *****************************************************************************/
  323. /**
  324.  * <Ring 0> Try to get a message from the src proc. If src is blocked sending
  325.  * the message, copy the message from it and unblock src. Otherwise the caller
  326.  * will be blocked.
  327.  * 
  328.  * @param current The caller, the proc who wanna receive.
  329.  * @param src     From whom the message will be received.
  330.  * @param m       The message ptr to accept the message.
  331.  * 
  332.  * @return  Zero if success.
  333.  *****************************************************************************/
  334. PRIVATE int msg_receive(struct proc* current, int src, MESSAGE* m)
  335. {
  336. struct proc* p_who_wanna_recv = current; /**
  337.   * This name is a little bit
  338.   * wierd, but it makes me
  339.   * think clearly, so I keep
  340.   * it.
  341.   */
  342. struct proc* p_from = 0; /* from which the message will be fetched */
  343. struct proc* prev = 0;
  344. int copyok = 0;
  345. assert(proc2pid(p_who_wanna_recv) != src);
  346. if ((p_who_wanna_recv->has_int_msg) &&
  347.     ((src == ANY) || (src == INTERRUPT))) {
  348. /* There is an interrupt needs p_who_wanna_recv's handling and
  349.  * p_who_wanna_recv is ready to handle it.
  350.  */
  351. MESSAGE msg;
  352. reset_msg(&msg);
  353. msg.source = INTERRUPT;
  354. msg.type = HARD_INT;
  355. assert(m);
  356. phys_copy(va2la(proc2pid(p_who_wanna_recv), m), &msg,
  357.   sizeof(MESSAGE));
  358. p_who_wanna_recv->has_int_msg = 0;
  359. assert(p_who_wanna_recv->p_flags == 0);
  360. assert(p_who_wanna_recv->p_msg == 0);
  361. assert(p_who_wanna_recv->p_sendto == NO_TASK);
  362. assert(p_who_wanna_recv->has_int_msg == 0);
  363. return 0;
  364. }
  365. /* Arrives here if no interrupt for p_who_wanna_recv. */
  366. if (src == ANY) {
  367. /* p_who_wanna_recv is ready to receive messages from
  368.  * ANY proc, we'll check the sending queue and pick the
  369.  * first proc in it.
  370.  */
  371. if (p_who_wanna_recv->q_sending) {
  372. p_from = p_who_wanna_recv->q_sending;
  373. copyok = 1;
  374. assert(p_who_wanna_recv->p_flags == 0);
  375. assert(p_who_wanna_recv->p_msg == 0);
  376. assert(p_who_wanna_recv->p_recvfrom == NO_TASK);
  377. assert(p_who_wanna_recv->p_sendto == NO_TASK);
  378. assert(p_who_wanna_recv->q_sending != 0);
  379. assert(p_from->p_flags == SENDING);
  380. assert(p_from->p_msg != 0);
  381. assert(p_from->p_recvfrom == NO_TASK);
  382. assert(p_from->p_sendto == proc2pid(p_who_wanna_recv));
  383. }
  384. }
  385. else {
  386. /* p_who_wanna_recv wants to receive a message from
  387.  * a certain proc: src.
  388.  */
  389. p_from = &proc_table[src];
  390. if ((p_from->p_flags & SENDING) &&
  391.     (p_from->p_sendto == proc2pid(p_who_wanna_recv))) {
  392. /* Perfect, src is sending a message to
  393.  * p_who_wanna_recv.
  394.  */
  395. copyok = 1;
  396. struct proc* p = p_who_wanna_recv->q_sending;
  397. assert(p); /* p_from must have been appended to the
  398.     * queue, so the queue must not be NULL
  399.     */
  400. while (p) {
  401. assert(p_from->p_flags & SENDING);
  402. if (proc2pid(p) == src) { /* if p is the one */
  403. p_from = p;
  404. break;
  405. }
  406. prev = p;
  407. p = p->next_sending;
  408. }
  409. assert(p_who_wanna_recv->p_flags == 0);
  410. assert(p_who_wanna_recv->p_msg == 0);
  411. assert(p_who_wanna_recv->p_recvfrom == NO_TASK);
  412. assert(p_who_wanna_recv->p_sendto == NO_TASK);
  413. assert(p_who_wanna_recv->q_sending != 0);
  414. assert(p_from->p_flags == SENDING);
  415. assert(p_from->p_msg != 0);
  416. assert(p_from->p_recvfrom == NO_TASK);
  417. assert(p_from->p_sendto == proc2pid(p_who_wanna_recv));
  418. }
  419. }
  420. if (copyok) {
  421. /* It's determined from which proc the message will
  422.  * be copied. Note that this proc must have been
  423.  * waiting for this moment in the queue, so we should
  424.  * remove it from the queue.
  425.  */
  426. if (p_from == p_who_wanna_recv->q_sending) { /* the 1st one */
  427. assert(prev == 0);
  428. p_who_wanna_recv->q_sending = p_from->next_sending;
  429. p_from->next_sending = 0;
  430. }
  431. else {
  432. assert(prev);
  433. prev->next_sending = p_from->next_sending;
  434. p_from->next_sending = 0;
  435. }
  436. assert(m);
  437. assert(p_from->p_msg);
  438. /* copy the message */
  439. phys_copy(va2la(proc2pid(p_who_wanna_recv), m),
  440.   va2la(proc2pid(p_from), p_from->p_msg),
  441.   sizeof(MESSAGE));
  442. p_from->p_msg = 0;
  443. p_from->p_sendto = NO_TASK;
  444. p_from->p_flags &= ~SENDING;
  445. unblock(p_from);
  446. }
  447. else {  /* nobody's sending any msg */
  448. /* Set p_flags so that p_who_wanna_recv will not
  449.  * be scheduled until it is unblocked.
  450.  */
  451. p_who_wanna_recv->p_flags |= RECEIVING;
  452. p_who_wanna_recv->p_msg = m;
  453. if (src == ANY)
  454. p_who_wanna_recv->p_recvfrom = ANY;
  455. else
  456. p_who_wanna_recv->p_recvfrom = proc2pid(p_from);
  457. block(p_who_wanna_recv);
  458. assert(p_who_wanna_recv->p_flags == RECEIVING);
  459. assert(p_who_wanna_recv->p_msg != 0);
  460. assert(p_who_wanna_recv->p_recvfrom != NO_TASK);
  461. assert(p_who_wanna_recv->p_sendto == NO_TASK);
  462. assert(p_who_wanna_recv->has_int_msg == 0);
  463. }
  464. return 0;
  465. }
  466. /*****************************************************************************
  467.  *                                inform_int
  468.  *****************************************************************************/
  469. /**
  470.  * <Ring 0> Inform a proc that an interrupt has occured.
  471.  * 
  472.  * @param task_nr  The task which will be informed.
  473.  *****************************************************************************/
  474. PUBLIC void inform_int(int task_nr)
  475. {
  476. struct proc* p = proc_table + task_nr;
  477. if ((p->p_flags & RECEIVING) && /* dest is waiting for the msg */
  478.     ((p->p_recvfrom == INTERRUPT) || (p->p_recvfrom == ANY))) {
  479. p->p_msg->source = INTERRUPT;
  480. p->p_msg->type = HARD_INT;
  481. p->p_msg = 0;
  482. p->has_int_msg = 0;
  483. p->p_flags &= ~RECEIVING; /* dest has received the msg */
  484. p->p_recvfrom = NO_TASK;
  485. assert(p->p_flags == 0);
  486. unblock(p);
  487. assert(p->p_flags == 0);
  488. assert(p->p_msg == 0);
  489. assert(p->p_recvfrom == NO_TASK);
  490. assert(p->p_sendto == NO_TASK);
  491. }
  492. else {
  493. p->has_int_msg = 1;
  494. }
  495. }
  496. /*****************************************************************************
  497.  *                                dump_proc
  498.  *****************************************************************************/
  499. PUBLIC void dump_proc(struct proc* p)
  500. {
  501. char info[STR_DEFAULT_LEN];
  502. int i;
  503. int text_color = MAKE_COLOR(GREEN, RED);
  504. int dump_len = sizeof(struct proc);
  505. out_byte(CRTC_ADDR_REG, START_ADDR_H);
  506. out_byte(CRTC_DATA_REG, 0);
  507. out_byte(CRTC_ADDR_REG, START_ADDR_L);
  508. out_byte(CRTC_DATA_REG, 0);
  509. sprintf(info, "byte dump of proc_table[%d]:n", p - proc_table); disp_color_str(info, text_color);
  510. for (i = 0; i < dump_len; i++) {
  511. sprintf(info, "%x.", ((unsigned char *)p)[i]);
  512. disp_color_str(info, text_color);
  513. }
  514. /* printl("^^"); */
  515. disp_color_str("nn", text_color);
  516. sprintf(info, "ANY: 0x%x.n", ANY); disp_color_str(info, text_color);
  517. sprintf(info, "NO_TASK: 0x%x.n", NO_TASK); disp_color_str(info, text_color);
  518. disp_color_str("n", text_color);
  519. sprintf(info, "ldt_sel: 0x%x.  ", p->ldt_sel); disp_color_str(info, text_color);
  520. sprintf(info, "ticks: 0x%x.  ", p->ticks); disp_color_str(info, text_color);
  521. sprintf(info, "priority: 0x%x.  ", p->priority); disp_color_str(info, text_color);
  522. sprintf(info, "pid: 0x%x.  ", p->pid); disp_color_str(info, text_color);
  523. sprintf(info, "name: %s.  ", p->name); disp_color_str(info, text_color);
  524. disp_color_str("n", text_color);
  525. sprintf(info, "p_flags: 0x%x.  ", p->p_flags); disp_color_str(info, text_color);
  526. sprintf(info, "p_recvfrom: 0x%x.  ", p->p_recvfrom); disp_color_str(info, text_color);
  527. sprintf(info, "p_sendto: 0x%x.  ", p->p_sendto); disp_color_str(info, text_color);
  528. sprintf(info, "nr_tty: 0x%x.  ", p->nr_tty); disp_color_str(info, text_color);
  529. disp_color_str("n", text_color);
  530. sprintf(info, "has_int_msg: 0x%x.  ", p->has_int_msg); disp_color_str(info, text_color);
  531. }
  532. /*****************************************************************************
  533.  *                                dump_msg
  534.  *****************************************************************************/
  535. PUBLIC void dump_msg(const char * title, MESSAGE* m)
  536. {
  537. int packed = 0;
  538. printl("{%s}<0x%x>{%ssrc:%s(%d),%stype:%d,%s(0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x)%s}%s",  //, (0x%x, 0x%x, 0x%x)}",
  539.        title,
  540.        (int)m,
  541.        packed ? "" : "n        ",
  542.        proc_table[m->source].name,
  543.        m->source,
  544.        packed ? " " : "n        ",
  545.        m->type,
  546.        packed ? " " : "n        ",
  547.        m->u.m3.m3i1,
  548.        m->u.m3.m3i2,
  549.        m->u.m3.m3i3,
  550.        m->u.m3.m3i4,
  551.        (int)m->u.m3.m3p1,
  552.        (int)m->u.m3.m3p2,
  553.        packed ? "" : "n",
  554.        packed ? "" : "n"/* , */
  555. );
  556. }