示例#1
0
文件: proc.c 项目: liangbizhi/bzOS
/**************************************************************************************************
 * 					msg_send
 **************************************************************************************************
 * <Ring 0> Send a message to the dest proc. If dest is blocked waiting for the message,
 * copy the message to it and unblock dest. 
 * Otherwise the caller will be blocked and appended to the dest's sending queue.
 *
 * @param current	The caller, the sender.
 * @param dest		To whom the message is sent.
 * @param msg		Pointer to the MESSAGE struct.
 *
 * @return		0 if success.
 *************************************************************************************************/
PRIVATE int msg_send(PROCESS* current, int dest, MESSAGE* msg){
	PROCESS* sender		= current;
	PROCESS* p_dest		= proc_table + dest;

	assert(proc2pid(sender) != dest);

	if(deadlock(proc2pid(sender), dest)){			/* Is there deadlock chain? */
		panic(">>DEADLOCK<< %s->%s", sender->name, p_dest->name);
	}
	/* dest is waiting for that msg or ANY msg. */
	if((p_dest->flags & RECEIVING) && (p_dest->recv_from == proc2pid(sender) || p_dest->recv_from == ANY)){
		assert(p_dest->p_msg);
		assert(msg);
		
		phys_copy(va2la(dest, p_dest->p_msg), va2la(proc2pid(sender), msg), sizeof(MESSAGE));

		p_dest->p_msg		= 0;
		p_dest->flags		&= ~RECEIVING;		/* dest has received the message */
		p_dest->recv_from	= NO_TASK;
		unblock(p_dest);

		assert(p_dest->flags == 0);
		assert(p_dest->p_msg == 0);
		assert(p_dest->recv_from == NO_TASK);
		assert(p_dest->send_to == NO_TASK);

		assert(sender->flags == 0);
		assert(sender->p_msg == 0);
		assert(sender->recv_from == NO_TASK);
		assert(sender->send_to == NO_TASK);
	}else{	/* However, dest is not waiting for the message */
		sender->flags		|= SENDING;
		assert(sender->flags == SENDING);
		sender->send_to		= dest;
		sender->p_msg		= msg;

		/* append to the sending queue */
		PROCESS* 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->flags == SENDING);
		assert(sender->p_msg != 0);
		assert(sender->recv_from == NO_TASK);
		assert(sender->send_to == dest);
	}
	return 0;
}
示例#2
0
int open(char* filename,int mode,int flag)
    //int sys_open(char* filename,int mode,int flag)
{
    struct m_inode *inode;

    struct file *f;
    int i;
    int fd = -1;                    //句柄
    //搜索没用过的句柄
    for(i = 0;i < NR_OPEN;i++)
    {       
        if(current->filp[i] == NULL)
        {
            fd = i;
            break;
        }

    }
    if(fd < 0 || fd > NR_OPEN)
    {
        panic("filp is full (PID %d)\n",proc2pid(current)); 
    }
    f = file_table;
    for(i = 0;i < NR_FILE;i++,f++)
    {
        if(!f->f_count)
        {
            break;
        }
    }
    if(i < 0 || i > NR_FILE)
    {
        panic("file_table is full (PID %d)\n",proc2pid(current));
    }
    (current->filp[fd] = f)->f_count++;
    //	printk("root_inode->i_dev = %d\n",root_inode->i_dev);
    if((i = open_namei(filename,mode,flag,&inode)) != 0)
    {
        current->filp[fd] = NULL;
        f->f_count = 0;
        return i;
    }
    //返回文件句柄
    //	printk("open inode->i_num = %d\n",inode->i_num);
    f->f_inode = inode;
    f->f_count = 1;
    f->f_flag = flag;
    f->f_mode = mode;
    f->f_pos = 0;
    //	printk("open:fd =  %d\n",fd);
    return fd;
}
示例#3
0
文件: proc.c 项目: liangbizhi/bzOS
/**************************************************************************************************
 * 					sys_sendrec
 **************************************************************************************************
 * <Ring 0> The core routine of system call 'sendrec'.
 * 
 * @param function	SEND, RECEIVE, BOTH
 * @param src_dest	To / From whom the message is transferred
 * @param msg		Pointer to the MESSAGE struct
 * @param proc		The caller process
 *
 * @return		0 if success
 *************************************************************************************************/
PUBLIC int sys_sendrec(int function, int src_dest, MESSAGE* msg, PROCESS* proc){
	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(proc);
	MESSAGE* mla	= (MESSAGE*) va2la(caller, msg);
	mla->source	= caller;		/* from 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 RECEIVE by 'send_recv()'.
	 */
	if(function == SEND){
		ret = msg_send(proc, src_dest, msg);
		if(ret != 0){
			return ret;
		}
	}else if(function == RECEIVE){
		ret = msg_receive(proc, src_dest, msg);
		if(ret != 0){
			return ret;
		}
	}else{
		panic("{sys_sendrec} invalid function: %d (SEND: %d, RECEIVE: %d).", function, SEND, RECEIVE);
	}
	return 0;
}
示例#4
0
文件: misc.c 项目: Jimx-/lyos
/**
 * <Ring 1> Perform the DUP and DUP2 syscalls.
 */
PUBLIC int do_dup(MESSAGE * p)
{
    int fd = p->FD;
    int newfd = p->NEWFD;

    struct file_desc * filp = pcaller->filp[fd];
    
    if (newfd == -1) {
        /* find a free slot in PROCESS::filp[] */
        int i;
        for (i = 0; i < NR_FILES; i++) {
            if (pcaller->filp[i] == 0) {
                newfd = i;
                break;
            }
        }
        if ((newfd < 0) || (newfd >= NR_FILES))
            panic("filp[] is full (PID:%d)", proc2pid(pcaller));
    }

    if (pcaller->filp[newfd] != 0) {
        /* close the file */
        p->FD = newfd;
        do_close(p);
    }

    filp->fd_cnt++;
    pcaller->filp[newfd] = filp;

    return newfd;
}
示例#5
0
PUBLIC int sys_sendrec(PROCESS *p, int function, int src_dest, MESSAGE *m)
{
    assert(k_reenter == 0);
    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);

    if (function == SEND) {
        ret = msg_send(p, src_dest, m);
    }
    else if (function == RECEIVE) {
        ret = msg_receive(p, src_dest, m);
    }
    else {
        panic("{sys_sendrec} invalid function: "
              "%d (SEND:%d, RECEIVE:%d).", function, SEND, RECEIVE);
    }

    return ret;
}
示例#6
0
文件: tty.c 项目: monomaniar/prettyos
/*
   int sys_write(char *buf,int len,struct task_struct *p_proc)
   {
   tty_write(&tty_table[p_proc->nr_tty],buf,len);
   return 0;
   }
   */
int sys_printx(char *s,int len,struct task_struct *p_proc)
{
    const char *p;
    char ch;
    char reenter_err[] = "? k_reenter is incorrect for unknown reason\n";

    if(k_reenter == 0)	//用户态下
    {
        p = (char *)va2la(proc2pid(p_proc),s);
    }
    else if(k_reenter > 0) //内核态
    {
        p =s;		
    }
    else
    {
        p = reenter_err;
    }

    ch = *p;
    if((ch == MAG_CH_PANIC) || (ch == MAG_CH_ASSERT && current < &proc_table[NR_SYSTEM_PROCS]))
    {
        disable_int(); //关中断
        char *v = (char *)V_MEM_BASE;
        const char *c = p + 1; //skip magic char
        while( v < ((char *)(V_MEM_BASE + V_MEM_SIZE)) && *c)
        {
            *v++ = *c++;
            *v++ = RED_COLOR; 
        }

        //halt processor until an enabled interrupt
        __asm__ __volatile__ ("hlt");
    }
    else
    {

        while((ch = *p++) != 0)	
        {
            out_char(tty_table[p_proc->nr_tty].p_console,ch);
        }
    }

    return 0;
}
示例#7
0
文件: misc.c 项目: Jimx-/lyos
/**
 * <Ring 1> Change the directory.  
 * @param  ppin     Directory to be change.
 * @param  string   Pathname.
 * @param  len      Length of pathname.
 * @return          Zero on success.
 */
PRIVATE int change_directory(struct inode ** ppin, char * string, int len)
{
    char pathname[MAX_PATH];
    if (len > MAX_PATH) return ENAMETOOLONG;

    /* fetch the name */
    data_copy(getpid(), D, pathname, proc2pid(pcaller), D, string, len);
    //phys_copy(va2pa(getpid(), pathname), va2pa(proc2pid(pcaller), string), len);
    pathname[len] = '\0';

    struct inode * pin = resolve_path(pathname, pcaller);
    if (!pin) return err_code;

    int retval = change_node(ppin, pin);

    put_inode(pin);
    return retval;
}
示例#8
0
PUBLIC int sys_sendrec(int function, int src_dest, Message *p_msg, Process *p_proc)
{
	 assert(k_reenter == 0);
	 assert((src_dest >= 0 && src_dest < NR_TASKS + NR_PROCS) ||
			src_dest == ANY ||
			src_dest == INTERRUPT);

	 int ret = 0;
	 int caller = proc2pid(p_proc);
	 Message *mla = (Message *)va2la(caller, p_msg);
	 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 SEDN followed by a RECEIVE
	 * by 'send_recv()'.
	 */
	 if(function == SEND)
	 {
		  ret = msg_send(p_proc, src_dest, p_msg);
		  if(ret != 0)
		  {
			   return ret;
		  }
	 }
	 else if(function == RECEIVE)
	 {
		  ret = msg_receive(p_proc, src_dest, p_msg);
		  if(ret != 0)
		  {
			   return ret;
		  }
	 }
	 else
	 {
		  panic("{sys_sendrec} invalid function: "
				"%d (SEND: %d, RECEIVE: %d).",
				function, SEND, RECEIVE);
	 }
	 return 0;
}
示例#9
0
文件: tty.c 项目: chenghuaijun/Orange
/*======================================================================*
                              sys_write
*======================================================================*/
PUBLIC int sys_printx(int _unused1, int _unused2, char* s, struct proc* p_proc)
{
	const char * p;
	char ch;

	char reenter_err[] = "? k_reenter is incorrect for unknown reason";
	reenter_err[0] = MAG_CH_PANIC;

	/**
	 * @note Code in both Ring 0 and Ring 1~3 may invoke printx().
	 * If this happens in Ring 0, no linear-physical address mapping
	 * is needed.
	 *
	 * @attention The value of `k_reenter' is tricky here. When
	 *   -# printx() is called in Ring 0
	 *      - k_reenter > 0. When code in Ring 0 calls printx(),
	 *        an `interrupt re-enter' will occur (printx() generates
	 *        a software interrupt). Thus `k_reenter' will be increased
	 *        by `kernel.asm::save' and be greater than 0.
	 *   -# printx() is called in Ring 1~3
	 *      - k_reenter == 0.
	 */
	if (k_reenter == 0)  /* printx() called in Ring<1~3> */
		p = va2la(proc2pid(p_proc), s);
	else if (k_reenter > 0) /* printx() called in Ring<0> */
		p = s;
	else	/* this should NOT happen */
		p = reenter_err;

	/**
	 * @note if assertion fails in any TASK, the system will be halted;
	 * if it fails in a USER PROC, it'll return like any normal syscall
	 * does.
	 */
	if ((*p == MAG_CH_PANIC) ||
	    (*p == MAG_CH_ASSERT && p_proc_ready < &proc_table[NR_TASKS])) {
		disable_int();
		char * v = (char*)V_MEM_BASE;
		const char * q = p + 1; /* +1: skip the magic char */

		while (v < (char*)(V_MEM_BASE + V_MEM_SIZE)) {
			*v++ = *q++;
			*v++ = RED_CHAR;
			if (!*q) {
				while (((int)v - V_MEM_BASE) % (SCR_WIDTH * 16)) {
					/* *v++ = ' '; */
					v++;
					*v++ = GRAY_CHAR;
				}
				q = p + 1;
			}
		}

		__asm__ __volatile__("hlt");
	}

	while ((ch = *p++) != 0) {
		if (ch == MAG_CH_PANIC || ch == MAG_CH_ASSERT)
			continue; /* skip the magic char */

		out_char(tty_table[p_proc->nr_tty].p_console, ch);
	}

	return 0;
}
示例#10
0
PUBLIC int do_open()
{
    int i = 0;
    int fd = -1; // return value
    char pathname[MAX_PATH];

    int flags = fs_msg.FLAGS;
    int name_len = fs_msg.NAME_LEN;
    int src = fs_msg.source;

    assert(name_len < MAX_PATH);
    phys_copy(
        (void *)va2la(TASK_FS, pathname),
        (void *)va2la(src, fs_msg.PATHNAME),
        name_len
    );
    pathname[name_len] = 0;

    /* 先在调用者进程中查找空闲文件描述符 */
    for (i = 0; i < NR_FILES; i++)
        if (pcaller->filp[i] == 0) {
            fd = i;
            break;
        }
    if ((fd < 0) || (fd >= NR_FILES))
        panic("filp[] is full (PID:%d)", proc2pid(pcaller));

    /* 然后在 f_desc_table 中查找空闲位置 */
    for (i = 0; i < NR_FILE_DESC; i++)
        if (f_desc_table[i].fd_inode == 0)
            break;
    if (i >= NR_FILE_DESC)
        panic("f_desc_table[] is full (PID:%d)", proc2pid(pcaller));

    /* 在磁盘中查找文件 */
    int inode_nr = search_file(pathname);

    /* 准备创建或打开文件 */
    struct inode *pin = 0;
    if (flags & O_CREAT) {
        if (inode_nr) {
            printl("file exists.\n");
            return -1;
        }
        else { // 文件不存在且标志位 O_CREAT
            pin = creat_file(pathname, flags);
        }
    }
    else {
        assert(flags & O_RDWR);

        char filename[MAX_PATH];
        struct inode * dir_inode;
        if (strip_path(filename, pathname, &dir_inode) != 0)
            return -1;
        pin = get_inode(dir_inode->i_dev, inode_nr);
    }

    /* 关联文件描述符 */
    if (pin) {
        /* proc <- fd (connects proc with file_descriptor) */
        pcaller->filp[fd] = &f_desc_table[i];

        /* fd <- inode (connects file_descriptor with inode) */
        f_desc_table[i].fd_mode = flags;
        f_desc_table[i].fd_pos = 0;
        f_desc_table[i].fd_inode = pin;

        int imode = pin->i_mode & I_TYPE_MASK;
        if (imode == I_CHAR_SPECIAL) {
            MESSAGE driver_msg;

            driver_msg.type = DEV_OPEN;
            int dev = pin->i_start_sect;
            driver_msg.DEVICE = MINOR(dev);
            assert(MAJOR(dev) == 4);
            assert(dd_map[MAJOR(dev)].driver_nr != INVALID_DRIVER);

            /* 如果是字符设备则交给该设备的驱动处理 */
            send_recv(BOTH, dd_map[MAJOR(dev)].driver_nr, &driver_msg);
        }
        else if (imode == I_DIRECTORY)
            assert(pin->i_num == ROOT_INODE);
        else
            assert(pin->i_mode == I_REGULAR);
    }
    else
        return -1; // open file failed

    return fd;
}
示例#11
0
文件: open.c 项目: kong123/STUDY
/**
 * Open a file and return the file descriptor.
 *
 * @return File descriptor if successful, otherwise a negative error code.
 *****************************************************************************/
PUBLIC int do_open()
{
    int fd = -1;		/* return value */

    char pathname[MAX_PATH];

    /* get parameters from the message */
    int flags = fs_msg.FLAGS;	/* access mode */
    int name_len = fs_msg.NAME_LEN;	/* length of filename */
    int src = fs_msg.source;	/* caller proc nr. */
    assert(name_len < MAX_PATH);
    phys_copy((void*)va2la(TASK_FS, pathname),
              (void*)va2la(src, fs_msg.PATHNAME),
              name_len);
    pathname[name_len] = 0;

    /* find a free slot in PROCESS::filp[] */
    int i;
    for (i = 0; i < NR_FILES; i++) {
        if (pcaller->filp[i] == 0) {
            fd = i;
            break;
        }
    }
    if ((fd < 0) || (fd >= NR_FILES))
        panic("filp[] is full (PID:%d)", proc2pid(pcaller));

    /* find a free slot in f_desc_table[] */
    for (i = 0; i < NR_FILE_DESC; i++)
        if (f_desc_table[i].fd_inode == 0)
            break;
    if (i >= NR_FILE_DESC)
        panic("f_desc_table[] is full (PID:%d)", proc2pid(pcaller));

    int inode_nr = search_file(pathname);

    struct inode * pin = 0;
    if (flags & O_CREAT) {
        if (inode_nr) {
            printl("file exists.\n");
            return -1;
        }
        else {
            pin = create_file(pathname, flags);
        }
    }
    else {
        assert(flags & O_RDWR);

        char filename[MAX_PATH];
        struct inode * dir_inode;
        if (strip_path(filename, pathname, &dir_inode) != 0)
            return -1;
        pin = get_inode(dir_inode->i_dev, inode_nr);
    }

    if (pin) {
        /* connects proc with file_descriptor */
        pcaller->filp[fd] = &f_desc_table[i];

        /* connects file_descriptor with inode */
        f_desc_table[i].fd_inode = pin;

        f_desc_table[i].fd_mode = flags;
        /* f_desc_table[i].fd_cnt = 1; */
        f_desc_table[i].fd_pos = 0;

        int imode = pin->i_mode & I_TYPE_MASK;

        if (imode == I_CHAR_SPECIAL) {
            MESSAGE driver_msg;
            driver_msg.type = DEV_OPEN;
            int dev = pin->i_start_sect;
            driver_msg.DEVICE = MINOR(dev);
            assert(MAJOR(dev) == 4);
            assert(dd_map[MAJOR(dev)].driver_nr != INVALID_DRIVER);
            send_recv(BOTH,
                      dd_map[MAJOR(dev)].driver_nr,
                      &driver_msg);
        }
        else if (imode == I_DIRECTORY) {
            assert(pin->i_num == ROOT_INODE);
        }
        else {
            assert(pin->i_mode == I_REGULAR);
        }
    }
    else {
        return -1;
    }

    return fd;
}
示例#12
0
文件: proc.c 项目: liangbizhi/bzOS
/**************************************************************************************************
 * 					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;
}
示例#13
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;
}
示例#14
0
文件: open.c 项目: Zach41/OS
PUBLIC int do_open() {
    int fd = -1;
    char pathname[MAX_PATH];

    int flags = fs_msg.FLAGS;
    int name_len = fs_msg.NAME_LEN;
    int src = fs_msg.source;
    assert(name_len < MAX_PATH);

    memcpy((void*)va2la(TASK_FS, pathname), (void*)va2la(src, fs_msg.PATHNAME), name_len);
    pathname[name_len] = 0;

    int i;
    for(i=0; i<NR_FILES; i++) {
	/* a empty filp item */
	if (pcaller -> filp[i] == 0)
	    break;
    }
    fd = i;
    /* printl("PATHNAME: %s, NAME_LEN: %d, FD: %d\n", pathname, name_len, fd); */
    if (fd <0 || fd >= NR_FILES)
	panic("file[] is full. PID: %d", proc2pid(pcaller));

    for(i=0; i<NR_FILE_DESC; i++) {
	/* a empty file descriptor */
	if (f_desc_table[i].fd_inode == 0)
	    break;
    }
    if (i >= NR_FILE_DESC)
	panic("f_desc_table[] is full. PID: %d", proc2pid(pcaller));

    // FIXME: search_file is wrong
    int inode_nr = search_file(pathname);
    
    struct inode* pin = 0;
    if (flags & O_CREAT) {
	if (inode_nr) {
	    /* file exists */
	    printl("file exists\n");
	    return -1;
	} else {
	    pin = create_file(pathname, flags);
	    /* dump_inode(pin); */
	}
    } else {
	assert(flags & O_RDWR);

	char filename[MAX_PATH];
	struct inode* dir_inode;
	if (strip_path(filename, pathname, &dir_inode) != 0)
	    return -1;
	pin = get_inode(dir_inode -> i_dev, inode_nr);
    }

    if (pin) {
	pcaller -> filp[fd] = &f_desc_table[i];

	f_desc_table[i].fd_inode = pin;

	f_desc_table[i].fd_mode  = flags;

	f_desc_table[i].fd_pos   = 0;
	f_desc_table[i].fd_cnt   = 1;

	int imode = pin -> i_mode & I_TYPE_MASK;

	if (imode == I_CHAR_SPECIAL) {
	    /* tty */
	    MESSAGE msg;
	    msg.type = DEV_OPEN;

	    int dev = pin -> i_start_sect;
	    assert(MAJOR(dev) == 4);
	    assert(dd_map[MAJOR(dev)].driver_nr != INVALID_DRIVER);

	    msg.DEVICE = MINOR(dev);
	    send_recv(BOTH, dd_map[MAJOR(dev)].driver_nr, &msg);
	} else if (imode == I_DIRECTORY) {
	    assert(pin -> i_num == ROOT_INODE);
	} else {
	    assert(pin -> i_mode == I_REGULAR);
	}
    } else {
	return -1;
    }

    return fd;
}
示例#15
0
文件: proc.c 项目: smilingjames/Sinix
/**
 * <Ring 0> Send a message to the dest proc. If dest is blocked waiting for
 * the message, copy the message to it and unblock dest. Otherwise the caller
 * will be blocked and appended to the dest's sending queue.
 * 
 * @param current  The caller, the sender.
 * @param dest     To whom the message is sent.
 * @param m        The message.
 * 
 * @return Zero if success.
 *****************************************************************************/
PRIVATE int msg_send(struct proc* current, int dest, MESSAGE* m)
{
	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;
}
示例#16
0
文件: proc.c 项目: smilingjames/Sinix
/**
 * <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;
}
示例#17
0
PRIVATE int msg_send(PROCESS *current, int dest, MESSAGE *m)
{
    PROCESS *sender = current;
    PROCESS *p_dest = proc_table + dest;

    assert(proc2pid(sender) != dest); // 不能自己给自己发消息

    if (deadlock(proc2pid(sender), dest))
        panic(">>DEADLOCK<< %s->%s", sender->name, p_dest->name);

    if ((p_dest->p_flags & RECEIVING) &&           // 如果目的进程正在等待接受消息
            (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;
        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 { // 如果目的进程没有等待接受本进程的消息
        sender->p_flags |= SENDING;         // 标志位置位,只有 p_flags == 0 该进程才会被调度
        assert(sender->p_flags == SENDING);
        sender->p_sendto = dest;
        sender->p_msg = m;

        /* 将自己添加到目的进程的发送者队列中去 */
        PROCESS *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 = NULL;

        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;
}