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行继续执行:
{
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行继续执行: