/* * Test4c * Verifies mailbox restart */ static void Test4c( void ) { char *msg = "mailbox start test"; int rc, count; TEST_INTRO( "Start Mailbox Test" ); // make sure we're empty to start drain_queue( SILENT ); verify_mailbox_count( 0, MBX_NO_STOP ); // Start the mailbox printf("Starting the mailbox...\n"); rc = ManageMailbox( MBX_NO_STOP, &count ); if (rc != 0) { printf("ManageMailbox() failed to start the mailbox! Reason=%s\n",mailbox_code(rc)); FAILURE_EXIT(); } // check that it's working send_recv_verify( msg, NOISY ); TEST_CLOSING(); }
/** * Tests sending message to stopped mailbox * @return [description] */ int test_send_stopped_mailbox(void) { // Variables to hold message data pid_t sender = getpid(); void *msg = malloc(MAX_MSG_SIZE); int len = MAX_MSG_SIZE, num_mesg; ManageMailbox(true, &num_mesg); // Try to get message int error = SendMsg(sender, msg, len, false); return error == MAILBOX_STOPPED; }
int main(int argc, char* argv[]) { int count = 22, myPID = getpid(), err; char msg[MAX_MSG_SIZE]; int sender, length; if((err = ManageMailbox(false, &count))) { printf("ManageMailbox failure: %d\n", err); return 1; }; if(count) { printf("count expected to be zero but instead found %d\n", count); return 2; } if((err = SendMsg(myPID, "test", 5, BLOCK))) { printf("SendMsg failure: %d\n", err); return 3; } if((err = ManageMailbox(false, &count))) { printf("ManageMailbox failure: %d\n", err); return 4; }; if(!count) return 5; if((err = RcvMsg(&sender, &msg, &length, BLOCK))) { printf("RcvMsg failure: %d\n", err); return 6; } if(sender != myPID) return 7; if(strcmp(msg, "test")) return 8; if(length != 5) return 9; if((err = ManageMailbox(true, &count))) { printf("ManageMailbox failure: %d\n", err); return 10; }; if(count) return 11; return 0; }
int blocked_wait_rcv_then_stopped() { pthread_t subt; int count; void* err; pthread_create(&subt, NULL, subthread_dorecieve, NULL); ManageMailbox(true, &count); pthread_join(subt, &err); int error = *(int*)err; free(err); return error == MAILBOX_STOPPED; }
asmlinkage long NewExit(int exit_code){ int group_dead; struct task_struct* tsk = current; struct Mailbox* self; // If the calling process does not have a mailbox, simply call the original exit system call if((self = HashFind(current->tgid))==NULL){ return (*ref_sys_exit)(exit_code); } // If the calling process is a kernel process, remove it's mailbox and then exit if(verifyPID(current->pid)==KERNPID){ spin_lock_irq(&creationLock); HashRemove(current->tgid); spin_unlock_irq(&creationLock); return (*ref_sys_exit)(exit_code); } group_dead = atomic_read(&tsk->signal->live) - 1; // If the calling process is the last process/thread in its group, it needs to delete the mailbox if(group_dead == 0){ // Manage the mailbox to stop it, which removes all waiting processes on send or receive ManageMailbox(true, NULL); spin_lock_irq(&self->lock); // If there are no processes waiting on either waiting queue, then flush the messages in the mailbox if (self->waitingFull != 0 || self->waitingEmpty != 0 || atomic_read(&self->references) != 0){ spin_unlock_irq(&self->lock); wait_event(self->canExit, self->waitingFull == 0 && self->waitingEmpty == 0 && atomic_read(&self->references) == 0); atomic_set(&self->references, -1); spin_lock_irq(&self->lock); } atomic_set(&self->references, -1); printk(KERN_INFO "%d is flushing %d messages. \n", current->tgid, self->numberofMessages); while(self->numberofMessages > 0){ struct Message* messages = self->message; //printk(KERN_INFO "Number of messages: %d\n", self->numberofMessages); self->message = self->message->next; kmem_cache_free(contentCache, messages->msg); kmem_cache_free(messageCache, messages); self->numberofMessages--; } //printk(KERN_INFO "Number of messages: %d\n", self->numberofMessages); // If there are no processes with a reference to the mailbox, delete the mailbox and hash link using HashRemove() spin_unlock_irq(&self->lock); spin_lock_irq(&creationLock); HashRemove(current->tgid); spin_unlock_irq(&creationLock); printk(KERN_INFO "Exiting and deleting mailbox for %d \n", current->tgid); //printk(KERN_INFO "Last member of thread group, so the mailbox has been deleted\n"); return (*ref_sys_exit)(exit_code); } //printk(KERN_INFO "Not the last member of thread group\n"); return (*ref_sys_exit)(exit_code); }
int closing_thread_does_not_stop_or_destroy_mailbox() { pthread_t thread; int error, count; error = SendMsg(getpid(), "Hello", 6, NO_BLOCK); expect_true(error == 0); pthread_create(&thread, NULL, useless_thread, NULL); pthread_join(thread, NULL); ManageMailbox(false, &count); expect_true(count == 1); return true; }
int main() { pid_t sender; sender = getpid(); int childPID = fork(); int status; if(childPID == 0){ void *msg[128]; int len; int count; ManageMailbox(false, &count); if(status= RcvMsg(&sender,msg,&len,false)) {printf("ERROR: %d\n", status);} else { printf("Message received.\n"); printf("Sender: %d\nMessage: %s\nLen: %d\n", sender, (char *) msg, len); } if(status= RcvMsg(&sender,msg,&len,false)) {printf("ERROR: %d\n", status);} else { printf("Message received.\n"); printf("Sender: %d\nMessage: %s\nLen: %d\n", sender, (char *) msg, len); } if(status= RcvMsg(&sender,msg,&len,false)) {printf("ERROR: %d\n", status);} else { printf("Message received.\n"); printf("Sender: %d\nMessage: %s\nLen: %d\n", sender, (char *) msg, len); } } else{ char mesg[] = "I am your father"; char mesg2[] = "Join me in the dark side!"; char mesg3[] = "Together we can rule the galaxy!"; printf("Sending Messages to child.\n"); if (status=SendMsg(childPID, mesg, 17, false)){ printf("Send failed with error %d\n", status); } if (status=SendMsg(childPID, mesg2, 26, false)){ printf("Send failed with error %d\n", status); } if (status=SendMsg(childPID, mesg3, 33, false)){ printf("Send failed with error %d\n", status); } } return 0; }
int msg_arg_error_invoke() { int error1 = ManageMailbox(false, NULL); // can't write to NULL, fail expect_true(error1 == MSG_ARG_ERROR); int error1_5 = ManageMailbox(true, NULL); // can't write to NULL, fail. Malformed command does not stop mailbox expect_true(error1_5 == MSG_ARG_ERROR); int error2 = SendMsg(getpid(),NULL, 6, NO_BLOCK); //can't read 6 from null, fail expect_true(error2 == MSG_ARG_ERROR); int error3 = SendMsg(getpid(),NULL,0,NO_BLOCK); // can read 0 from null, pass expect_true(error3 == 0); int error4 = RcvMsg(NULL, NULL, NULL, NO_BLOCK); // can't send null to null, fail expect_true(error4 == MSG_ARG_ERROR); pid_t sender; char msg[MAX_MSG_SIZE]; int len; int error5 = RcvMsg(NULL, msg, &len, NO_BLOCK); // can't read to null, fail expect_true(error5 == MSG_ARG_ERROR); int error6 = RcvMsg(&sender, msg, NULL, NO_BLOCK); // can't read to null, fail expect_true(error6 == MSG_ARG_ERROR); int error7 = RcvMsg(&sender, msg, &len, NO_BLOCK); // can read to all, pass expect_true(error7 == 0); expect_true(len == 0); int len2; SendMsg(getpid(),"Hello",6,NO_BLOCK); int error8 = RcvMsg(&sender, NULL, &len2, NO_BLOCK); // can't read to null, len isn't 0, fail expect_true(error8 == MSG_ARG_ERROR); return true; }
int blocked_wait_then_stopped() { pid_t child = fork(); int error; if (child) { int i; for (i = 0; i < 32; i++) { SendMsg(child, "Hello", 6, NO_BLOCK); } error = SendMsg(child, "Hello", 6, BLOCK); return (error == MAILBOX_STOPPED); } else { usleep(5000); ManageMailbox(true, &error); exit(0); } }
int mailbox_stopped(void) { int i, error; pid_t me = getpid(); void* msg = malloc(MAX_MSG_SIZE); ManageMailbox(true, &i); error = SendMsg(me, "Hello", 6, BLOCK); if (error != MAILBOX_STOPPED) { free(msg); return false; } error = RcvMsg(&me, msg, &i, BLOCK); free(msg); return (error == MAILBOX_STOPPED); }
asmlinkage long NewExitGroup(int exit_code){ int group_dead; struct task_struct* tsk = current; struct Mailbox* self; if((self = HashFind(current->tgid))==NULL){ return (*ref_sys_exit_group)(exit_code); } if(verifyPID(current->pid)==KERNPID){ spin_lock_irq(&creationLock); HashRemove(current->tgid); spin_unlock_irq(&creationLock); return (*ref_sys_exit_group)(exit_code); } group_dead = atomic_read(&tsk->signal->live) - 1; if(group_dead == 0){ ManageMailbox(true, NULL); spin_lock_irq(&self->lock); if (self->waitingFull != 0 || self->waitingEmpty != 0 || atomic_read(&self->references) != 0){ spin_unlock_irq(&self->lock); wait_event(self->canExit, self->waitingFull == 0 && self->waitingEmpty == 0 && atomic_read(&self->references) == 0); atomic_set(&self->references, -1); spin_lock_irq(&self->lock); } atomic_set(&self->references, -1); printk(KERN_INFO "%d is flushing %d messages. \n", current->tgid, self->numberofMessages); while(self->numberofMessages > 0){ struct Message* messages = self->message; //printk(KERN_INFO "Number of messages: %d\n", self->numberofMessages); self->message = self->message->next; kmem_cache_free(contentCache, messages->msg); kmem_cache_free(messageCache, messages); self->numberofMessages--; } //printk(KERN_INFO "Number of messages: %d\n", self->numberofMessages); spin_unlock_irq(&self->lock); spin_lock_irq(&creationLock); HashRemove(current->tgid); spin_unlock_irq(&creationLock); printk(KERN_INFO "Exiting and deleting mailbox for %d \n", current->tgid); //printk(KERN_INFO "Last member of thread group, so the mailbox has been deleted\n"); return (*ref_sys_exit_group)(exit_code); } //printk(KERN_INFO "Not the last member of thread group\n"); return (*ref_sys_exit_group)(exit_code); }
/** * Tests if programs that chose to wait until able to send a message behave properly * @return [description] */ int test_message_overflow_wait(void) { int childCounter; int childPID; for(childCounter = 0; childCounter < CHILD_NUM; childCounter++) { childPID = fork(); if(childPID == 0){ pid_t sender; void *msg[MAX_MSG_SIZE]; int len; RcvMsg(&sender, msg, &len, true); char myMesg[] = "I am your child"; int error = SendMsg(sender, myMesg, 16, true); exit(0); } else { char mesg[] = "I am your father"; SendMsg(childPID, mesg, 17, true); } } int failed = 0; int msgCounter; int num_mesg; ManageMailbox(false, &num_mesg); for(msgCounter = 0; msgCounter < CHILD_NUM; msgCounter++) { pid_t aSender; char *reply[MAX_MSG_SIZE]; int mLen; if(RcvMsg(&aSender, reply, &mLen, true)) { failed++; } } int status; return (failed == 0); }
int recieve_messages_even_after_stopped() { pid_t me = getpid(), you; int i = 15, j, k, len, error; error = SendMsg(me, &i, sizeof(int), NO_BLOCK); expect_true(error == 0); error = ManageMailbox(true, &j); expect_true(error == 0); expect_true(j == 1); error = RcvMsg(&you, &k, &len, NO_BLOCK); expect_true(error == 0); expect_true(k == i); expect_true(len == sizeof(int)); expect_true(me == you); error = RcvMsg(&you, &k, &len, NO_BLOCK); expect_true(error == MAILBOX_STOPPED); return true; }
int main() { int childCounter; pid_t mypid; for(childCounter = 0; childCounter < CHILD_NUM; childCounter++) { int childPID = fork(); if(childPID == 0){ pid_t sender; void *msg[128]; int len; bool block = true; RcvMsg(&sender,msg,&len,block); printf("Parent %d, Message: %s\n", sender, (char *)msg); char myMesg[] = "I am your child"; if(SendMsg(sender, myMesg, 16, block)) { printf("Child send failed.\n"); } return 0; } else{ char mesg[] = "I am your father"; if (SendMsg(childPID, mesg, 17, false)){ printf("Send failed\n"); } wait(&childPID); } } usleep(3000000); printf("Parent awoke from sleep.\n"); ManageMailbox(true, &childCounter); printf("Mailbox stopped.\n"); // retrieve all enqueued messages while( childCounter > 0) { pid_t aSender; void *reply[128]; int mLen; RcvMsg(&aSender, reply, &mLen, true); printf("Child %d, dequeueing # %d Message: %s\n", aSender, childCounter, (char *)reply); childCounter--; } // attempt to retrieve from and empty and stopped mailbox pid_t aSender2; void *reply2[128]; int mLen2; RcvMsg(&aSender2, reply2, &mLen2, true); // atempt to send a message to a stopped mailbox mypid = getpid(); int childPID2 = fork(); if(childPID2 == 0){ pid_t sender3; void *msg3[128]; int len3; bool block = true; RcvMsg(&sender3,msg3,&len3,block); printf("Message: %s\n", (char *)msg3); char myMesg2[] = "I am your child"; printf("PID = %d\n", mypid); if(SendMsg(mypid, myMesg2, 16, block)) { printf("Child send failed.\n"); } } else{ char mesg3[] = "I am your father"; if (SendMsg(childPID2, mesg3, 17, false)){ printf("Send failed\n"); } wait(&childPID2); } return 0; }
int main (){ char mesg[] = "This is a test"; int mypid = getpid(); int ret; int count = 0; /*******************************test1************************************/ printf("\n\n###TEST1###\n"); printf("Sending Message to pid = -3, expect MAILBOX_INVALID (1004)\n"); ret = SendMsg(-3, mesg, 15, false); if (ret){ printf("Send failed: error = %d\n", ret); if (ret == 1004) count++; } /*******************************test2************************************/ printf("\n\n###TEST2###\n"); printf("Sending message to my child (which does not exist) expect MAILBOX_INVALID (1004)\n"); ret = SendMsg(mypid+1, mesg, 15, false); if (ret){ printf("Send failed: error = %d\n", ret); if (ret == 1004) count++; } /*******************************test3************************************/ printf("\n\n###TEST3###\n"); printf("Sending message to kernel task (pid == 1) expect MAILBOX_INVALID (1004)\n"); ret = SendMsg(1, mesg, 15, false); if (ret){ printf("Send failed: error = %d\n", ret); if (ret == 1004) count++; } /*******************************test4************************************/ printf("\n\n###TEST4###\n"); printf("Try to receive message from a empty mailbox, expect MAILBOX_EMPTY (1002)\n"); printf("Sending Message to myself.\n"); ret = SendMsg(mypid, mesg, 15, false); if (ret){ printf("Send failed: error = %d, mypid = %d", ret, mypid); } void *msg[128]; int len; bool block = true; int sender; ret = RcvMsg(&sender,msg,&len,block); if (ret){ printf("Receive failed for the first time! error = %d\n", ret); } else{ printf("Message received.\n"); printf("Message: %s, sender = %d, len = %d, mypid = %d return = %d\n", (char *) msg, sender, len, mypid, ret); } printf("Now try receive message again, should get error MAILBOX_EMPTY (1002)\n"); ret = RcvMsg(&sender,msg,&len,false); if (ret) { printf("Receive failed for the second time! error = %d\n", ret); if (ret == MAILBOX_EMPTY) count++; } /*******************************test5************************************/ printf("\n\n###TEST5###\n"); printf("Try sending a null message to myself\n"); printf("Expect error MSG_ARG_ERROR (1006)\n"); ret = SendMsg(mypid, NULL, 15, false); if (ret) { printf("Send failed: error = %d, mypid = %d\n", ret, mypid); if (ret == MSG_ARG_ERROR) count++; } else { printf("Message received.\n"); printf("Message: %s, sender = %d, len = %d, mypid = %d return = %d\n", (char *) msg, sender, len, mypid, ret); } /*******************************test6************************************/ printf("\n\n###TEST6###\n"); printf("Try receiving message from a mailbox that has been stopped, expect error MAILBOX_STOPPED (1003)\n"); printf("Sending Message to myself.\n"); ret = SendMsg(mypid, mesg, 15, false); if (ret){ printf("Send failed: error = %d, mypid = %d", ret, mypid); } int msgCount; //now stop mailbox ManageMailbox(true, &msgCount); printf("Mailbox stopped.\n"); printf("There are %d messages in the mailbox", msgCount); ret = RcvMsg(&sender,msg,&len,false); printf("Try recieve message\n"); printf("Should recieve message from non-empty stopped mailbox\n"); if (ret){ printf("Receive failed! error = %d\n", ret); } else{ printf("Message received.\n"); printf("Message: %s, sender = %d, len = %d, mypid = %d return = %d\n", (char *) msg, sender, len, mypid, ret); } ret = RcvMsg(&sender,msg,&len,false); printf("Try recieve message again\n"); printf("Should not recieve message from empty stopped mailbox\n"); if (ret) { printf("Receive failed! error = %d\n", ret); count++; } else{ printf("Message received.\n"); printf("Message: %s, sender = %d, len = %d, mypid = %d return = %d\n", (char *) msg, sender, len, mypid, ret); } /*******************************test7************************************/ printf("\n\n###TEST7###\n"); printf("Try sending message to a mailbox that has been stopped, expect error MAILBOX_STOPPED (1003)\n"); printf("Now try send message to myself again, my mailbox is stopped so should get error\n"); ret = SendMsg(mypid, mesg, 15, false); if (ret){ printf("Send failed: error = %d, mypid = %d\n", ret, mypid); if (ret == MAILBOX_STOPPED) count++; } else{ printf("Message Sent.\n"); } /*******************************test8************************************/ printf("\n\n###TEST8###\n"); printf("Try sending a message to myself with negative length, expect error MSG_LENGTH_ERROR (1005)\n"); ret = SendMsg(mypid, mesg, -3, false); if (ret) { printf("Send failed: error = %d, mypid = %d\n", ret, mypid); if (ret == MSG_LENGTH_ERROR) count++; } else { printf("Message received.\n"); printf("Message: %s, sender = %d, len = %d, mypid = %d return = %d\n", (char *) msg, sender, len, mypid, ret); } /*******************************test9************************************/ printf("\n\n###TEST9###\n"); printf("Try sending a message to myself with length greater than max, expect error MSG_LENGTH_ERROR (1005)\n"); ret = SendMsg(mypid, mesg, 200, false); if (ret) { printf("Send failed: error = %d, mypid = %d\n", ret, mypid); if (ret == MSG_LENGTH_ERROR) count++; } else { printf("Message received.\n"); printf("Message: %s, sender = %d, len = %d, mypid = %d return = %d\n", (char *) msg, sender, len, mypid, ret); } printf("%d/9 tests passed\n", count); return 0; }