/** * receive message from given sender */ asmlinkage long sys_RcvMsg(pid_t *sender, void *msg, int *len, bool block){ pid_t my_pid = current->pid; mailbox* mb = NULL; signal* signal = NULL; message* this_mail; pid_t *a_sender; void *a_msg; int *a_len; signal = get_signal(my_pid); if (signal == NULL) { signal = create_signal(my_pid, TRUE); wait_event(signal->wait_null, mb != NULL); } mb = get_mailbox(my_pid); if ((mb->stop) && (mb->size == 0)) return MAILBOX_STOPPED; if ((block == NO_BLOCK) && (mb->size == 0)) return MAILBOX_EMPTY; if ((block == BLOCK) && (mb->size == 0)) { wait_event(mb->wait_empty, mb->size != 0); printk("LLLLLLLLLLLOOOPPPP"); } spin_lock(&(mb->lock)); this_mail = get_msg(&mb); spin_unlock(&(mb->lock)); if (this_mail == NULL) return MAILBOX_ERROR;; a_sender = &(this_mail->sender); a_msg = this_mail->content; a_len = &(this_mail->len); if (((*a_len) > MAX_MSG_SIZE) || ((*a_len) < 0)) return MSG_LENGTH_ERROR; if ((copy_to_user(sender, a_sender, sizeof(pid_t)))) return MSG_ARG_ERROR; if ((copy_to_user(msg, a_msg, *a_len))) return MSG_ARG_ERROR; if ((copy_to_user(len, a_len, sizeof(int)))) return MSG_ARG_ERROR; spin_lock(&(mb->lock)); rm_message(&mb); spin_unlock(&(mb->lock)); //successful return 0; }
static int dequeue_message(int for_proc, void *msg_data, size_t msg_size, void *session) { int result, queue_lock_held = 0, read_partial_message; size_t bytes_read = 0, bytes_to_read, qsize, qbytes_read; unsigned char *read_from, *write_to; void *qdata; if (!has_message(for_proc, session)) return 0; result = take_queue_lock(session); if (result == -1) { goto error; } queue_lock_held = 1; while (has_message(for_proc, session) && bytes_read < msg_size) { get_message(for_proc, &qdata, &qsize, &qbytes_read, session); read_partial_message = (qsize - qbytes_read) > (msg_size - bytes_read); read_from = ((unsigned char *) qdata) + qbytes_read; write_to = ((unsigned char *) msg_data) + bytes_read; if (read_partial_message) bytes_to_read = msg_size - bytes_read; else bytes_to_read = qsize - qbytes_read; memcpy(write_to, read_from, bytes_to_read); bytes_read += bytes_to_read; qbytes_read += bytes_to_read; update_bytes_read(for_proc, qbytes_read, session); if (!read_partial_message) { assert(qbytes_read == qsize); rm_message(for_proc, session); } } result = release_queue_lock(session); if (result == -1) { goto error; } queue_lock_held = 0; return bytes_read; error: if (queue_lock_held) release_queue_lock(session); return -1; }