异步消息流程

PUBLIC int get_ticks()
{
disp_str("get_ticks ");
//pause_system();
MESSAGE msg;
reset_msg(&msg);
msg.type = GET_TICKS;
send_recv(BOTH, TASK_SYS, &msg);
return msg.RETVAL;
}

PUBLIC int send_recv(int function, int src_dest, MESSAGE* msg)
{
disp_str("send_recv ");


int ret = 0;


if (function == RECEIVE)
memset(msg, 0, sizeof(MESSAGE));


switch (function) {
case BOTH:
ret = sendrec(SEND, src_dest, msg);
if (ret == 0)
ret = sendrec(RECEIVE, src_dest, msg);
break;
case SEND:
case RECEIVE:
ret = sendrec(function, src_dest, msg);
break;
default:
assert((function == BOTH) ||
       (function == SEND) || (function == RECEIVE));
break;
}


return ret;
}

; ====================================================================================
;                  sendrec(int function, int src_dest, MESSAGE* msg);
; ====================================================================================
; Never call sendrec() directly, call send_recv() instead.
sendrec:
mov eax, _NR_sendrec
mov ebx, [esp + 4] ; function
mov ecx, [esp + 8] ; src_dest
mov edx, [esp + 12] ; p_msg
int INT_VECTOR_SYS_CALL
ret


PUBLIC system_call sys_call_table[NR_SYS_CALL] = {sys_printx,
       sys_sendrec};



; =============================================================================
;                                 sys_call
; =============================================================================
sys_call:
        call    save


        sti
push esi


push dword [p_proc_ready]
push edx
push ecx
push ebx
call    [sys_call_table + eax * 4]
add esp, 4 * 4


pop esi
mov     [esi + EAXREG - P_STACKBASE], eax
cli


ret




PUBLIC int sys_sendrec(int function, int src_dest, MESSAGE* m, struct proc* p)
{
disp_str("sys_sendrec ");
assert(k_reenter == 0); /* make sure we are not in ring0 */
assert((src_dest >= 0 && src_dest < NR_TASKS + NR_PROCS) ||
       src_dest == ANY ||
       src_dest == INTERRUPT);


int ret = 0;
int caller = proc2pid(p);
MESSAGE* mla = (MESSAGE*)va2la(caller, m);
mla->source = caller;


assert(mla->source != src_dest);


/**
* Actually we have the third message type: BOTH. However, it is not
* allowed to be passed to the kernel directly. Kernel doesn't know
* it at all. It is transformed into a SEND followed by a RECEIVE
* by `send_recv()'.
*/
if (function == SEND) 
{
ret = msg_send(p, src_dest, m);
if (ret != 0)
return ret;
}
else if (function == RECEIVE) {
ret = msg_receive(p, src_dest, m);
if (ret != 0)
return ret;
}
else {
panic("{sys_sendrec} invalid function: "
      "%d (SEND:%d, RECEIVE:%d).", function, SEND, RECEIVE);
}


return 0;
}


PRIVATE int msg_send(struct proc* current, int dest, MESSAGE* m)
{
disp_str("msg_send ");
struct proc* sender = current;
struct proc* p_dest = proc_table + dest; /* proc dest */


assert(proc2pid(sender) != dest);


/* check for deadlock here */
if (deadlock(proc2pid(sender), dest)) {
panic(">>DEADLOCK<< %s->%s", sender->name, p_dest->name);
}


if ((p_dest->p_flags & RECEIVING) && /* dest is waiting for the msg */
    (p_dest->p_recvfrom == proc2pid(sender) ||
     p_dest->p_recvfrom == ANY)) {
assert(p_dest->p_msg);
assert(m);


phys_copy(va2la(dest, p_dest->p_msg),
  va2la(proc2pid(sender), m),
  sizeof(MESSAGE));
p_dest->p_msg = 0;
p_dest->p_flags &= ~RECEIVING; /* dest has received the msg */
p_dest->p_recvfrom = NO_TASK;
unblock(p_dest);


assert(p_dest->p_flags == 0);
assert(p_dest->p_msg == 0);
assert(p_dest->p_recvfrom == NO_TASK);
assert(p_dest->p_sendto == NO_TASK);
assert(sender->p_flags == 0);
assert(sender->p_msg == 0);
assert(sender->p_recvfrom == NO_TASK);
assert(sender->p_sendto == NO_TASK);
}
else { /* dest is not waiting for the msg */
sender->p_flags |= SENDING;
assert(sender->p_flags == SENDING);
sender->p_sendto = dest;
sender->p_msg = m;


/* append to the sending queue */
struct proc * p;
if (p_dest->q_sending) {
p = p_dest->q_sending;
while (p->next_sending)
p = p->next_sending;
p->next_sending = sender;
}
else {
p_dest->q_sending = sender;
}
sender->next_sending = 0;


block(sender);


assert(sender->p_flags == SENDING);
assert(sender->p_msg != 0);
assert(sender->p_recvfrom == NO_TASK);
assert(sender->p_sendto == dest);
}


return 0;
}

上边这个函数返回0后
从第26行继续执行:



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值