URL
https://opencores.org/ocsvn/or1k/or1k/trunk
Subversion Repositories or1k
[/] [or1k/] [trunk/] [rtems-20020807/] [c/] [src/] [tests/] [psxtests/] [psxmsgq01/] [init.c] - Rev 1026
Go to most recent revision | Compare with Previous | Blame | View Log
/* * COPYRIGHT (c) 1989-1999. * On-Line Applications Research Corporation (OAR). * * The license and distribution terms for this file may be * found in the file LICENSE in this distribution or at * http://www.OARcorp.com/rtems/license.html. * * init.c,v 1.9 2002/08/02 00:53:21 joel Exp */ #define CONFIGURE_INIT #include "system.h" #include <sched.h> #include <fcntl.h> #include <time.h> #include <tmacros.h> #include <signal.h> /* signal facilities */ typedef struct { char msg[ 50 ]; int size; unsigned int priority; }Test_Message_t; Test_Message_t Predefined_Msgs[MAXMSG+1]; Test_Message_t Predefined_Msgs[MAXMSG+1] = { { "12345678", 9, MQ_PRIO_MAX-1 }, /* Max Length Message med */ { "", 1, 1 }, /* NULL Message low */ { "Last", 5, MQ_PRIO_MAX }, /* Queue Full Message hi */ { "No Message", 0, MQ_PRIO_MAX-1 }, /* 0 length Message med */ { "1", 2, 0 }, /* Cause Overflow Behavior */ }; int Priority_Order[MAXMSG+1] = { 2, 0, 3, 1, MAXMSG }; typedef struct { mqd_t mq; Test_Queue_Types index; char *name; int oflag; int maxmsg; int msgsize; int count; } Test_queue_type; Test_queue_type Test_q[ NUMBER_OF_TEST_QUEUES ] = { { 0, 0, "Qread", ( O_CREAT | O_RDONLY | O_NONBLOCK ), MAXMSG, MSGSIZE, 0 }, { 0, 1, "Qwrite", ( O_CREAT | O_WRONLY | O_NONBLOCK ), MAXMSG, MSGSIZE, 0 }, { 0, 2, "Qnoblock", ( O_CREAT | O_RDWR | O_NONBLOCK ), MAXMSG, MSGSIZE, 0 }, { 0, 3, "Qblock", ( O_CREAT | O_RDWR ) , MAXMSG, MSGSIZE, 0 }, { 0, 4, "Qdefault", ( O_CREAT | O_RDWR ) , 10, 16, 0 }, { 0, 5, "mq6", ( O_CREAT | O_WRONLY | O_NONBLOCK ), MAXMSG, MSGSIZE, 0 }, }; #define RW_NAME Test_q[ RW_QUEUE ].name #define DEFAULT_NAME Test_q[ DEFAULT_RW ].name #define RD_NAME Test_q[ RD_QUEUE ].name #define WR_NAME Test_q[ WR_QUEUE ].name #define BLOCKING_NAME Test_q[ BLOCKING ].name #define CLOSED_NAME Test_q[ CLOSED ].name #define RW_ATTR Test_q[ RW_QUEUE ].oflag #define DEFAULT_ATTR Test_q[ DEFAULT_RW ].oflag #define RD_ATTR Test_q[ RD_QUEUE ].oflag #define WR_ATTR Test_q[ WR_QUEUE ].oflag #define BLOCK_ATTR Test_q[ BLOCKING ].oflag #define CLOSED_ATTR Test_q[ CLOSED ].oflag /* * Outputs a header at each test section. */ void Start_Test( char *description ) { printf( "_______________%s\n", description ); } void Validate_attributes( mqd_t mq, int oflag, int msg_count ) { int status; struct mq_attr attr; status = mq_getattr( mq, &attr ); fatal_posix_service_status( status, 0, "mq_getattr valid return status"); if ( mq != Test_q[ DEFAULT_RW ].mq ){ fatal_int_service_status((int)attr.mq_maxmsg, MAXMSG, "maxmsg attribute" ); fatal_int_service_status((int)attr.mq_msgsize,MSGSIZE,"msgsize attribute"); } fatal_int_service_status((int)attr.mq_curmsgs, msg_count, "count attribute" ); fatal_int_service_status((int)attr.mq_flags, oflag, "flag attribute" ); } char Queue_Name[PATH_MAX + 2]; #define Get_Queue_Name( i ) Test_q[i].name char *Build_Queue_Name( int i ) { sprintf(Queue_Name,"mq%d", i+1 ); return Queue_Name; } char *Get_Too_Long_Name() { int i; for ( i=0; i< PATH_MAX+1; i++ ) Queue_Name[i] = 'N'; Queue_Name[i] = '\0'; return Queue_Name; } void open_test_queues() { struct mq_attr attr; int status; Test_queue_type *tq; int que; attr.mq_maxmsg = MAXMSG; attr.mq_msgsize = MSGSIZE; puts( "Init: Open Test Queues" ); for( que = 0; que < NUMBER_OF_TEST_QUEUES; que++ ) { tq = &Test_q[ que ]; if ( que == DEFAULT_RW) Test_q[que].mq = mq_open( tq->name, tq->oflag, 0x777, NULL ); else Test_q[que].mq = mq_open( tq->name, tq->oflag, 0x777, &attr ); assert( Test_q[que].mq != (-1) ); } status = mq_close( Test_q[CLOSED].mq ); fatal_posix_service_status( status, 0, "mq_close message queue"); status = mq_unlink( CLOSED_NAME ); fatal_posix_service_status( status, 0, "mq_unlink message queue"); } /* * Opens CONFIGURE_MAXIMUM_POSIX_MESSAGE_QUEUES then leaves size queues * opened but closes the rest. */ void validate_mq_open_error_codes() { int i; mqd_t n_mq2; struct mq_attr attr; int status; mqd_t open_mq[CONFIGURE_MAXIMUM_POSIX_MESSAGE_QUEUES + 1]; attr.mq_maxmsg = MAXMSG; attr.mq_msgsize = MSGSIZE; Start_Test( "mq_open errors" ); /* * XXX EINVAL - inappropriate name was given for the message queue */ /* * EINVAL - Create with negative maxmsg. */ attr.mq_maxmsg = -1; puts( "Init: mq_open - Create with maxmsg (-1) (EINVAL)" ); n_mq2 = mq_open( "mq2", O_CREAT | O_RDONLY, 0x777, &attr); fatal_posix_service_status( (int) n_mq2, (int ) (-1), "mq_open error return status" ); fatal_posix_service_status( errno, EINVAL, "mq_open errno EINVAL"); attr.mq_maxmsg = MAXMSG; /* * EINVAL - Create withnegative msgsize. */ attr.mq_msgsize = -1; puts( "Init: mq_open - Create with msgsize (-1) (EINVAL)" ); n_mq2 = mq_open( "mq2", O_CREAT | O_RDONLY, 0x777, &attr); fatal_posix_service_status( (int) n_mq2, (int ) (-1), "mq_open error return status" ); fatal_posix_service_status( errno, EINVAL, "mq_open errno EINVAL"); attr.mq_msgsize = MSGSIZE; /* * ENOENT - Open a non-created file. */ puts( "Init: mq_open - Open new mq without create flag (ENOENT)" ); n_mq2 = mq_open( "mq3", O_EXCL | O_RDONLY, 0x777, NULL); fatal_posix_service_status( (int) n_mq2, (int ) (-1), "mq_open error return status" ); fatal_posix_service_status( errno, ENOENT, "mq_open errno ENOENT"); /* * XXX EINTR - call was interrupted by a signal */ /* * ENAMETOOLONG - Give a name greater than PATH_MAX. */ puts( "Init: mq_open - Open with too long of a name (ENAMETOOLONG)" ); n_mq2 = mq_open( Get_Too_Long_Name(), O_CREAT | O_RDONLY, 0x777, NULL ); fatal_posix_service_status( (int) n_mq2, (int ) (-1), "mq_open error return status" ); fatal_posix_service_status( errno, ENAMETOOLONG, "mq_open errno ENAMETOOLONG"); /* * XXX - ENAMETOOLONG - Give a name greater than NAME_MAX * Per implementation not possible. */ /* * EEXIST - Create an existing queue. */ puts( "Init: mq_open - Create an Existing mq (EEXIST)" ); open_mq[0] = mq_open( Build_Queue_Name(0), O_CREAT | O_RDWR | O_NONBLOCK, 0x777, NULL ); assert( open_mq[0] != (-1) ); n_mq2 = mq_open( Build_Queue_Name(0), O_CREAT | O_EXCL | O_RDONLY, 0x777, NULL); fatal_posix_service_status( (int) n_mq2, (int ) (-1), "mq_open error return status" ); fatal_posix_service_status( errno, EEXIST, "mq_open errno EEXIST"); status = mq_unlink( Build_Queue_Name(0) ); fatal_posix_service_status( status, 0, "mq_unlink message queue"); status = mq_close( open_mq[0]); fatal_posix_service_status( status, 0, "mq_close message queue"); /* * Open maximum number of message queues */ puts( "Init: mq_open - SUCCESSFUL" ); for (i = 0; i < CONFIGURE_MAXIMUM_POSIX_MESSAGE_QUEUES; i++) { open_mq[i] = mq_open( Build_Queue_Name(i), O_CREAT | O_RDWR | O_NONBLOCK, 0x777, NULL ); assert( open_mq[i] != (-1) ); assert( open_mq[i] ); /*XXX - Isn't there a more general check */ /* JRS printf( "mq_open 0x%x %s\n", open_mq[i], Build_Queue_Name(i) ); */ } /* * XXX EACCES - permission to create is denied. */ /* * XXX EACCES - queue exists permissions specified by o_flag are denied. */ /* * XXX EMFILE - Too many message queues in use by the process */ /* * ENFILE - Too many message queues open in the system */ puts( "Init: mq_open - system is out of resources (ENFILE)" ); n_mq2 = mq_open( Build_Queue_Name(i), O_CREAT | O_RDONLY, 0x777, NULL ); fatal_posix_service_status( (int) n_mq2, (int ) (-1), "mq_open error return status" ); fatal_posix_service_status( errno, ENFILE, "mq_open errno ENFILE"); /* * Unlink and Close all queues. */ puts( "Init: mq_close and mq_unlink (mq3...mqn) - SUCCESSFUL" ); for (i = 0; i < CONFIGURE_MAXIMUM_POSIX_MESSAGE_QUEUES; i++) { status = mq_close( open_mq[i]); fatal_posix_service_status( status, 0, "mq_close message queue"); status = mq_unlink( Build_Queue_Name(i) ); if ( status == -1 ) perror( "mq_unlink" ); fatal_posix_service_status( status, 0, "mq_unlink message queue"); /* JRS printf( "mq_close/mq_unlink 0x%x %s\n", open_mq[i], Build_Queue_Name(i) ); */ } } void validate_mq_unlink_error_codes() { int status; Start_Test( "mq_unlink errors" ); /* * XXX - EACCES Permission Denied */ /* * ENAMETOOLONG - Give a name greater than PATH_MAX. */ puts( "Init: mq_unlink - mq_unlink with too long of a name (ENAMETOOLONG)" ); status = mq_unlink( Get_Too_Long_Name() ); fatal_posix_service_status( status, -1, "mq_unlink error return status"); fatal_posix_service_status( errno, ENAMETOOLONG, "mq_unlink errno ENAMETOOLONG"); /* * XXX - ENAMETOOLONG - Give a name greater than NAME_MAX * Per implementation not possible. */ /* * ENOENT - Unlink an unopened queue */ puts( "Init: mq_unlink - A Queue not opened (ENOENT)" ); status = mq_unlink( CLOSED_NAME ); fatal_posix_service_status( status, -1, "mq_unlink error return status"); fatal_posix_service_status( errno, ENOENT, "mq_unlink errno ENOENT"); /* * XXX - The following were not listed in the POSIX document as * possible errors. Under other commands the EINVAL is * given for these conditions. */ /* * EINVAL - Unlink a queue with no name */ puts( "Init: mq_unlink (NULL) - EINVAL" ); status = mq_unlink( NULL ); fatal_posix_service_status( status, -1, "mq_unlink error return status"); fatal_posix_service_status( errno, EINVAL, "mq_unlink errno value"); /* * EINVAL - Unlink a queue with a null name */ puts( "Init: mq_unlink (\"\") - EINVAL" ); status = mq_unlink( "" ); fatal_posix_service_status( status, -1, "mq_unlink error return status"); fatal_posix_service_status( errno, EINVAL, "mq_unlink errno value"); } void validate_mq_close_error_codes() { int status; Start_Test( "mq_close errors" ); /* * EBADF - Close a queue that is not open. */ puts( "Init: mq_close - unopened queue (EBADF)" ); status = mq_close( Test_q[CLOSED].mq ); fatal_posix_service_status( status, -1, "mq_close error return status"); fatal_posix_service_status( errno, EBADF, "mq_close errno EBADF"); } void validate_mq_getattr_error_codes() { struct mq_attr attr; int status; Start_Test( "mq_getattr errors" ); /* * EBADF - Get the attributes from a closed queue. */ puts( "Init: mq_getattr - unopened queue (EBADF)" ); status = mq_getattr( Test_q[CLOSED].mq, &attr ); fatal_posix_service_status( status, -1, "mq_close error return status"); fatal_posix_service_status( errno, EBADF, "mq_close errno EBADF"); /* * XXX - The following are not listed in the POSIX manual but * may occur. */ /* * EINVAL - NULL attributes */ puts( "Init: mq_getattr - NULL attributes (EINVAL)" ); status = mq_getattr( Test_q[RW_QUEUE].mq, NULL ); fatal_posix_service_status( status, -1, "mq_close error return status"); fatal_posix_service_status( errno, EINVAL, "mq_close errno EINVAL"); } void Send_msg_to_que( int que, int msg ) { Test_Message_t *ptr = &Predefined_Msgs[msg]; int status; status = mq_send( Test_q[que].mq, ptr->msg, ptr->size , ptr->priority ); fatal_posix_service_status( status, 0, "mq_send valid return status"); Test_q[que].count++; } void Show_send_msg_to_que( char *task_name, int que, int msg ) { Test_Message_t *ptr = &Predefined_Msgs[msg]; printf( "%s mq_send - to %s msg: %s priority %d\n", task_name, Test_q[que].name, ptr->msg, ptr->priority); Send_msg_to_que( que, msg ); } void verify_queues_full( char *task_name ) { int que; /* * Validate that the queues are full. */ printf( "%s Verify Queues are full\n", task_name ); for( que = RW_QUEUE; que < CLOSED; que++ ) Validate_attributes( Test_q[que].mq, Test_q[que].oflag, Test_q[que].count ); } void verify_queues_empty( char *task_name ) { int que; printf( "%s Verify Queues are empty\n", task_name ); for( que = RW_QUEUE; que < CLOSED; que++ ) Validate_attributes( Test_q[que].mq, Test_q[que].oflag, 0 ); } int fill_message_queues( char *task_name ) { int msg; int que; verify_queues_empty( task_name ); /* * Fill Queue with predefined messages. */ printf( "%s Fill Queues with messages\n", task_name ); for(msg=0; msg<MAXMSG; msg++){ for( que = RW_QUEUE; que < CLOSED; que++ ) { Send_msg_to_que( que, msg ); } } verify_queues_full( "Init:" ); return msg; } void Read_msg_from_que( int que, int msg ) { unsigned int priority; Test_Message_t *ptr; int status; char message[100]; char err_msg[100]; ptr = &Predefined_Msgs[msg]; status = mq_receive(Test_q[ que ].mq, message, 100, &priority ); Test_q[que].count--; sprintf( err_msg, "%s msg %s size failure", Test_q[ que ].name, ptr->msg ); fatal_int_service_status( status, ptr->size, err_msg ); assert( !strcmp( message, ptr->msg ) ); strcpy( message, "No Message" ); sprintf( err_msg,"%s msg %s size failure", Test_q[ que ].name, ptr->msg ); fatal_int_service_status(priority, ptr->priority, err_msg ); } int empty_message_queues( char *task_name ) { int que; int i; printf( "%s Empty all Queues\n", task_name ); for( que = RW_QUEUE; que < CLOSED; que++ ) { for(i=0; Test_q[que].count != 0; i++ ) Read_msg_from_que( que, Priority_Order[i] ); Validate_attributes( Test_q[ que].mq, Test_q[ que ].oflag, 0 ); } return 0; } /* * Returns the number of messages queued after the test on the * first queue. */ int validate_mq_send_error_codes( ) { int status; int i; char *str; Start_Test( "mq_send errors" ); /* * EBADF - Write to a closed queue. */ puts( "Init: mq_send - Closed message queue (EBADF)" ); status = mq_send( Test_q[CLOSED].mq, "", 1, 0 ); fatal_posix_service_status( status, -1, "mq_send error return status"); fatal_posix_service_status( errno, EBADF, "mq_send errno EBADF"); /* * EBADF - Write to a read only queue. */ puts( "Init: mq_send - Read only message queue (EBADF)" ); status = mq_send( Test_q[ RD_QUEUE ].mq, "", 1, 0 ); fatal_posix_service_status( status, -1, "mq_send error return status"); fatal_posix_service_status( errno, EBADF, "mq_send errno EBADF"); /* * XXX - EINTR Signal interrupted the call. * puts( "Init: mq_send - UNSUCCESSFUL (EINTR)" ); status = mq_send( Test_q, "", 0xffff, 0 ); fatal_posix_service_status( status, -1, "mq_send error return status"); fatal_posix_service_status( errno, E, "mq_send errno E"); */ /* * EINVAL priority is out of range. */ puts( "Init: mq_send - Priority out of range (EINVAL)" ); status = mq_send( Test_q[ RW_QUEUE ].mq, "", 1, MQ_PRIO_MAX + 1 ); fatal_posix_service_status( status, -1, "mq_send error return status"); fatal_posix_service_status( errno, EINVAL, "mq_send errno EINVAL"); /* * EMSGSIZE - Message size larger than msg_len * Validates that msgsize is stored correctly. */ puts( "Init: mq_send - Message longer than msg_len (EMSGSIZE)" ); status = mq_send( Test_q[ RW_QUEUE ].mq, "", MSGSIZE+1, 0 ); fatal_posix_service_status( status, -1, "mq_send error return status"); fatal_posix_service_status( errno, EMSGSIZE, "mq_send errno EMSGSIZE"); i = fill_message_queues( "Init:" ); /* * ENOSYS - send not supported puts( "Init: mq_send - Blocking Queue overflow (ENOSYS)" ); status = mq_send( n_mq1, Predefined_Msgs[i], 0, 0 ); fatal_posix_service_status( status, -1, "mq_send error return status"); fatal_posix_service_status( errno, EBADF, "mq_send errno EBADF"); status = mq_close( n_mq1 ); fatal_posix_service_status( status, 0, "mq_close message queue"); status = mq_unlink( "read_only" ); fatal_posix_service_status( status, 0, "mq_unlink message queue"); */ /* * EAGAIN - O_NONBLOCK and message queue is full. */ puts( "Init: mq_send - on a FULL non-blocking queue with (EAGAIN)" ); str = Predefined_Msgs[i].msg; status = mq_send(Test_q[RW_QUEUE].mq, str, 0, 0 ); fatal_posix_service_status( status, -1, "mq_send error return status"); fatal_posix_service_status( errno, EAGAIN, "mq_send errno EAGAIN"); return i-1; } void validate_mq_receive_error_codes( ) { int status; char message[100]; unsigned int priority; Start_Test( "mq_receive errors" ); /* * EBADF - Not A Valid Message Queue */ puts( "Init: mq_receive - Unopened message queue (EBADF)" ); status = mq_receive( Test_q[CLOSED].mq, message, 100, &priority ); fatal_posix_service_status( status, -1, "mq_ error return status"); fatal_posix_service_status( errno, EBADF, "mq_receive errno EBADF"); /* * EBADF - Queue not opened to read */ puts( "Init: mq_receive - Write only queue (EBADF)" ); status = mq_receive( Test_q[WR_QUEUE].mq, message, 100, &priority ); fatal_posix_service_status( status, -1, "mq_ error return status"); fatal_posix_service_status( errno, EBADF, "mq_receive errno EBADF"); /* * EMSGSIZE - Size is less than the message size attribute */ puts( "Init: mq_receive - Size is less than the message (EMSGSIZE)" ); status = mq_receive( Test_q[RW_QUEUE].mq, message, Predefined_Msgs[0].size-1, &priority ); fatal_posix_service_status( status, -1, "mq_ error return status"); fatal_posix_service_status( errno, EMSGSIZE, "mq_receive errno EMSGSIZE"); /* * EAGAIN - O_NONBLOCK and Queue is empty */ verify_queues_full( "Init:" ); empty_message_queues( "Init:" ); puts( "Init: mq_receive - Queue is empty (EAGAIN)" ); status = mq_receive( Test_q[RW_QUEUE].mq, message, 100, &priority ); fatal_posix_service_status( status, -1, "mq_ error return status"); fatal_posix_service_status( errno, EAGAIN, "mq_receive errno EAGAIN"); /* * XXX - EINTR - Interrupted by a signal */ /* * XXX - EBADMSG - a data corruption problem. */ /* * XXX - ENOSYS - mq_receive not supported */ } void verify_open_functionality() { mqd_t n_mq; Start_Test( "mq_open functionality" ); /* * Validate a second open returns the same message queue. */ #if 0 puts( "Init: mq_open - Open an existing mq ( same id )" ); n_mq = mq_open( RD_NAME, 0 ); fatal_posix_service_status( (int) n_mq, (int ) Test_q[RD_QUEUE].mq, "mq_open error return status" ); #endif } void verify_unlink_functionality() { mqd_t n_mq; int status; Start_Test( "mq_unlink functionality" ); /* * Unlink the message queue, then verify an open of the same name produces a * different message queue. */ puts( "Init: Unlink and Open without closing SUCCESSFUL" ); status = mq_unlink( DEFAULT_NAME ); fatal_posix_service_status( status, 0, "mq_unlink locked message queue"); n_mq = mq_open( DEFAULT_NAME, DEFAULT_ATTR, 0x777, NULL ); assert( n_mq != (-1) ); assert( n_mq != Test_q[ DEFAULT_RW ].mq ); status = mq_unlink( DEFAULT_NAME ); fatal_posix_service_status( status, 0, "mq_unlink locked message queue"); status = mq_close( Test_q[ DEFAULT_RW ].mq ); fatal_posix_service_status( status, 0, "mq_close message queue"); Test_q[ DEFAULT_RW ].mq = n_mq; } void verify_close_functionality() { int i; int status; Start_Test( "Unlink and Close All Files" ); for (i=0; i<DEFAULT_RW; i++) { status = mq_unlink( Get_Queue_Name(i) ); fatal_posix_service_status( status, 0, "mq_unlink message queue"); status = mq_close( Test_q[i].mq ); fatal_posix_service_status( status, 0, "mq_close message queue"); } } void verify_timed_send_queue( int que, int is_blocking ) { struct timespec timeout; struct timeval tv1, tv2, tv3; struct timezone tz1, tz2; int len; int status; char *msg; timeout.tv_sec = 1; timeout.tv_nsec = 0; printf( "Init: mq_timedsend - on queue %s ", Test_q[que].name); len = Predefined_Msgs[MAXMSG].size; msg = Predefined_Msgs[MAXMSG].msg; gettimeofday( &tv1, &tz1 ); status = mq_timedsend( Test_q[que].mq, msg, len , 0, &timeout ); gettimeofday( &tv2, &tz2 ); tv3.tv_sec = tv2.tv_sec - tv1.tv_sec; tv3.tv_usec = tv2.tv_usec - tv1.tv_usec; if ( is_blocking ) { /* Don't verify the non-blocking queue */ fatal_int_service_status( status, -1, "mq_timedsend status"); fatal_posix_service_status( errno, ETIMEDOUT, "errno ETIMEDOUT"); } printf("Init: %d sec %d us\n", tv3.tv_sec, tv3.tv_usec ); if ( is_blocking ) /* non-blocking queue */ assert( tv3.tv_sec == 1 ); else assert( tv3.tv_sec == 0 ); if ( que == DEFAULT_RW ) Test_q[que].count++; } void verify_timed_send() { int que; Start_Test( "mq_timedsend" ); for( que = RW_QUEUE; que < CLOSED; que++ ) { if ( que == BLOCKING ) verify_timed_send_queue( que, 1 ); else verify_timed_send_queue( que, 0 ); } } void verify_timed_receive_queue( char *task_name, int que, int is_blocking ) { char message[ 100 ]; unsigned int priority; struct timespec tm; struct timeval tv1, tv2, tv3; struct timezone tz1, tz2; int status; tm.tv_sec = 1; tm.tv_nsec = 0; printf( "Init: %s mq_timedreceive - on queue %s ", task_name, Test_q[que].name); gettimeofday( &tv1, &tz1 ); status = mq_timedreceive( Test_q[ que ].mq, message, 100, &priority, &tm ); gettimeofday( &tv2, &tz2 ); tv3.tv_sec = tv2.tv_sec - tv1.tv_sec; tv3.tv_usec = tv2.tv_usec - tv1.tv_usec; fatal_int_service_status( status, -1, "mq_timedreceive status"); if ( is_blocking ) fatal_posix_service_status( errno, ETIMEDOUT, "errno ETIMEDOUT"); printf( "Init: %d sec %d us\n", tv3.tv_sec, tv3.tv_usec ); if ( is_blocking ) assert( tv3.tv_sec == 1 ); else assert( tv3.tv_sec == 0 ); } void verify_timed_receive() { int que; Start_Test( "mq_timedreceive" ); for( que = RW_QUEUE; que < CLOSED; que++ ) { if (( que == BLOCKING ) || ( que == DEFAULT_RW )) verify_timed_receive_queue( "Init:", que, 1 ); else verify_timed_receive_queue( "Init:", que, 0 ); } } #if (0) void verify_set_attr() { struct mq_attr save_attr[ NUMBER_OF_TEST_QUEUES ]; struct mq_attr attr; int i; int status; attr.mq_maxmsg = 0; attr.mq_msgsize = 0; Start_Test( "mq_setattr" ); puts( "Init: set_attr all queues to blocking" ); for(i=0; i<CLOSED; i++) { attr.mq_flags = Test_q[i].oflag & (~O_NONBLOCK ); status = mq_setattr( Test_q[i].mq, &attr, &save_attr[i] ); fatal_int_service_status( status, 0, "mq_setattr valid return status"); Validate_attributes( Test_q[i].mq, attr.mq_flags, 0 ); } for( i = RW_QUEUE; i < CLOSED; i++ ) { verify_timed_receive_queue( "Init:", i, 1 ); } for(i=0; i<CLOSED; i++) { attr.mq_flags = Test_q[i].oflag & (~O_NONBLOCK ); status = mq_setattr( Test_q[i].mq, &save_attr[i], NULL ); fatal_int_service_status( status, 0, "mq_setattr valid return status"); Validate_attributes( Test_q[i].mq, Test_q[i].oflag, 0 ); } } #endif void wait_for_signal( sigset_t *waitset, int sec, int expect_signal ) { siginfo_t siginfo; int status; struct timespec timeout; int signo; siginfo.si_code = -1; siginfo.si_signo = -1; siginfo.si_value.sival_int = -1; timeout.tv_sec = sec; timeout.tv_nsec = 0; status = sigemptyset( waitset ); assert( !status ); status = sigaddset( waitset, SIGUSR1 ); assert( !status ); printf( "waiting on any signal for %d seconds.\n", sec ); signo = sigtimedwait( waitset, &siginfo, &timeout ); if (expect_signal) { fatal_int_service_status( signo, SIGUSR1, "got SISUSR1" ); } else { fatal_int_service_status( signo, -1, "error return status"); fatal_posix_service_status( errno, EAGAIN, "errno EAGAIN"); } } void verify_notify() { struct sigevent event; int status; timer_t timer_id; sigset_t set; Start_Test( "mq_notify" ); /* timer create */ event.sigev_notify = SIGEV_SIGNAL; event.sigev_signo = SIGUSR1; if (timer_create (CLOCK_REALTIME, &event, &timer_id) == -1) fatal_posix_service_status( errno, 0, "errno ETIMEDOUT"); /* block the timer signal */ sigemptyset( &set ); sigaddset( &set, SIGUSR1 ); pthread_sigmask( SIG_BLOCK, &set, NULL ); /* * EBADF - Not A Valid Message Queue */ puts( "Init: mq_notify - Unopened message queue (EBADF)" ); status = mq_notify( Test_q[CLOSED].mq, NULL ); fatal_posix_service_status( status, -1, "mq_ error return status"); fatal_posix_service_status( errno, EBADF, "mq_receive errno EBADF"); /* * Create ... */ /* * XXX setup notification */ printf( "_____mq_notify - notify when %s gets a message\n",RW_NAME); status = mq_notify( Test_q[RW_QUEUE].mq, &event ); fatal_posix_service_status( status, 0, "mq_notify valid status"); wait_for_signal( &set, 3, 0 ); /* * Send and verify signal occurs and registration is removed. */ puts( "Init: Verify Signal when send" ); Show_send_msg_to_que( "Init:", RW_QUEUE, 0 ); wait_for_signal( &set, 3, 1 ); Read_msg_from_que( RW_QUEUE, 0 ); puts( "Init: Verify No Signal when send" ); Show_send_msg_to_que( "Init:", RW_QUEUE, 0 ); wait_for_signal( &set, 3, 0 ); Read_msg_from_que( RW_QUEUE, 0 ); /* * EBUSY - Already Registered */ printf( "____mq_notify - notify when %s gets a message\n",RD_NAME); status = mq_notify( Test_q[RW_QUEUE].mq, &event ); fatal_posix_service_status( status, 0, "mq_notify valid status"); wait_for_signal( &set, 3, 0 ); puts( "Init: mq_notify - (EBUSY)" ); status = mq_notify( Test_q[RW_QUEUE].mq, &event ); fatal_posix_service_status( status, -1, "mq_notify error return status"); fatal_posix_service_status( errno, EBUSY, "mq_notify errno EBUSY"); /* * Verify NULL removes registration. */ puts( "Init: mq_notify - Remove notification with null" ); status = mq_notify( Test_q[RW_QUEUE].mq, NULL ); fatal_posix_service_status( status, 0, "mq_notify valid status"); puts( "Init: Verify No Signal when send" ); Show_send_msg_to_que( "Init:", RW_QUEUE, 0 ); wait_for_signal( &set, 3, 0 ); Read_msg_from_que( RW_QUEUE, 0 ); } void verify_with_threads() { int status; pthread_t id; Test_Message_t *ptr; unsigned int priority; char message[100]; /* * Create a task then block until the task sends the message. * Task tests set attributes so one queue will have a thread * blocked while attributes are changed. */ Start_Test( "multi-thread Task 4 Receive Test" ); status = pthread_create( &id, NULL, Task_4, NULL ); assert( !status ); puts( "Init: mq_receive - Empty queue changes to non-blocking (EAGAIN)" ); status = mq_receive( Test_q[BLOCKING].mq, message, 100, &priority ); fatal_int_service_status( status, -1, "mq_receive error return status"); fatal_posix_service_status( errno, EAGAIN, "mq_receive errno EAGAIN"); print_current_time( "Init: ", "" ); /* * Create a task then block until the task sends the message. * Task tests set attributes so one queue will have a thread * blocked while attributes are changed. */ Start_Test( "multi-thread Task 1 Test" ); status = pthread_create( &id, NULL, Task_1, NULL ); assert( !status ); Read_msg_from_que( BLOCKING, 0 ); /* Block until init writes */ print_current_time( "Init: ", "" ); /* * Create a task then block until the task reads a message. */ Start_Test( "multi-thread Task 4 Send Test" ); fill_message_queues( "Init:" ); status = pthread_create( &id, NULL, Task_4, NULL ); assert( !status ); puts( "Init: mq_send - Full queue changes to non-blocking (EAGAIN)" ); status = mq_send(Test_q[BLOCKING].mq, message, 0, 0 ); fatal_posix_service_status( status, -1, "mq_send error return status"); fatal_posix_service_status( errno, EAGAIN, "mq_send errno EAGAIN"); verify_queues_full( "Init:" ); empty_message_queues( "Init:" ); /* * Create a task then block until the task reads a message. */ Start_Test( "multi-thread Task 2 Test" ); fill_message_queues( "Init:" ); status = pthread_create( &id, NULL, Task_2, NULL ); assert( !status ); Show_send_msg_to_que( "Init:", BLOCKING, Priority_Order[0] ); print_current_time( "Init: ", "" ); verify_queues_full( "Init:" ); empty_message_queues( "Init:" ); /* * Create a task then block until it deletes and closes all queues. * EBADF - Queue unlinked and closed while blocked */ Start_Test( "multi-thread Task 3 Test" ); fill_message_queues( "Init:" ); status = pthread_create( &id, NULL, Task_3, NULL ); assert( !status ); puts( "Init: mq_send - Block while thread deletes queue (EBADF)" ); ptr = &Predefined_Msgs[0]; status = mq_send( Test_q[BLOCKING].mq, ptr->msg, ptr->size , ptr->priority ); fatal_posix_service_status( status, -1, "mq_send error return status"); fatal_posix_service_status( errno, EBADF, "mq_send errno EBADF"); } void validate_mq_setattr() { struct mq_attr attr; struct mq_attr save_attr[ NUMBER_OF_TEST_QUEUES ]; int status; int i; /* * EBADF - Get the attributes from a closed queue. */ puts( "Task1:mq_setattr - unopened queue (EBADF)" ); status = mq_setattr( Test_q[CLOSED].mq, &attr, NULL ); fatal_posix_service_status( status, -1, "mq_setattr error return status"); fatal_posix_service_status( errno, EBADF, "mq_setattr errno EBADF"); /* * XXX - The following are not listed in the POSIX manual but * may occur. */ /* * EINVAL - NULL attributes */ puts( "Task1:mq_setattr - NULL attributes (EINVAL)" ); status = mq_setattr( Test_q[RW_QUEUE].mq, NULL, NULL ); fatal_posix_service_status( status, -1, "mq_setattr error return status"); fatal_posix_service_status( errno, EINVAL, "mq_setattr errno EINVAL"); /* * Verify change queues to blocking, by verifying all queues block * for a timed receive. */ puts( "Init: set_attr all queues to blocking" ); for(i=0; i<CLOSED; i++) { attr.mq_flags = Test_q[i].oflag & (~O_NONBLOCK ); status = mq_setattr( Test_q[i].mq, &attr, &save_attr[i] ); fatal_int_service_status( status, 0, "mq_setattr valid return status"); Validate_attributes( Test_q[i].mq, attr.mq_flags, 0 ); } for( i = RW_QUEUE; i < CLOSED; i++ ) { verify_timed_receive_queue( "Init:", i, 1 ); } /* * Restore restore all queues to their old attribute. */ for(i=0; i<CLOSED; i++) { status = mq_setattr( Test_q[i].mq, &save_attr[i], NULL ); fatal_int_service_status( status, 0, "mq_setattr valid return status"); Validate_attributes( Test_q[i].mq, Test_q[i].oflag, 0 ); } } void *POSIX_Init( void *argument ) { puts( "\n\n*** POSIX MESSAGE QUEUE TEST ***" ); validate_mq_open_error_codes( ); open_test_queues(); validate_mq_unlink_error_codes(); validate_mq_close_error_codes(); verify_unlink_functionality(); validate_mq_setattr( ); validate_mq_send_error_codes(); validate_mq_getattr_error_codes(); verify_timed_send(); validate_mq_receive_error_codes(); verify_timed_receive(); verify_open_functionality(); verify_notify(); verify_with_threads(); puts( "*** END OF POSIX MESSAGE QUEUE TEST ***" ); rtems_test_exit( 0 ); return NULL; /* just so the compiler thinks we returned something */ } void *Task_1 ( void *argument ) { /* Block Waiting for a message */ print_current_time( "Task_1: ", "" ); Show_send_msg_to_que( "Task_1:", BLOCKING, 0 ); puts( "Task_1: pthread_exit" ); pthread_exit( NULL ); /* switch to Init */ assert( 0 ); return NULL; /* just so the compiler thinks we returned something */ } void *Task_2( void *argument ) { print_current_time( "Task_2: ", "" ); /* Block waiting to send a message */ verify_queues_full( "Task_2:" ); Read_msg_from_que( BLOCKING, Priority_Order[0] ); /* Cause context switch */ puts( "Task_2: pthread_exit" ); pthread_exit( NULL ); /* switch to Init */ return NULL; /* just so the compiler thinks we returned something */ } void *Task_3 ( void *argument ) { print_current_time( "Task_3: ", "" ); /* * close and unlink all queues. */ verify_close_functionality( "Task_3: " ); puts( "Task_3: pthread_exit" ); pthread_exit( NULL ); /* switch to Init */ return NULL; /* just so the compiler thinks we returned something */ } void *Task_4 ( void *argument ) { struct mq_attr attr; int status; int count; print_current_time( "Task_4: ", "" ); /* * Set the count to the number of messages in the queue. */ status = mq_getattr( Test_q[BLOCKING].mq, &attr ); fatal_posix_service_status( status, 0, "mq_getattr valid return status"); count = attr.mq_curmsgs; puts("Task_4: Set queue to non-blocking"); attr.mq_flags = Test_q[BLOCKING].oflag | O_NONBLOCK; status = mq_setattr( Test_q[BLOCKING].mq, &attr, NULL ); fatal_int_service_status( status, 0, "mq_setattr valid return status"); Validate_attributes( Test_q[BLOCKING].mq, attr.mq_flags, count ); puts("Task_4: Return queue to blocking"); attr.mq_flags = Test_q[BLOCKING].oflag; status = mq_setattr( Test_q[BLOCKING].mq, &attr, NULL ); fatal_int_service_status( status, 0, "mq_setattr valid return status"); Validate_attributes( Test_q[BLOCKING].mq, attr.mq_flags, count ); puts( "Task_4: pthread_exit" ); pthread_exit( NULL ); /* switch to Init */ return NULL; /* just so the compiler thinks we returned something */ } void *Task_5 ( void *argument ) { print_current_time( "Task_5: ", "" ); puts( "Task_5: pthread_exit" ); pthread_exit( NULL ); /* switch to Init */ return NULL; /* just so the compiler thinks we returned something */ } void *Task_ ( void *argument ) { print_current_time( "Task_: ", "" ); puts( "Task_: pthread_exit" ); pthread_exit( NULL ); /* switch to Init */ return NULL; /* just so the compiler thinks we returned something */ }
Go to most recent revision | Compare with Previous | Blame | View Log