posix/aio*: Added notification on request completion

The patch adds the generation of a notification after an Asynchronous I/O
request has been completed. The notification is generated using the aio_sigevent
filed in the aiocb struct, as defined by the posix specifiations.
A new control, ensuring the validity of the field, is added on each call to
aio_read(), aio_write() and aio_fsync().
The patch also adds tests to cover the new code, and fixes formatting errors of
various aio files.
This commit is contained in:
alessandronardin
2024-07-13 11:43:30 +02:00
parent e58ff8984c
commit 3b96aaddde
20 changed files with 543 additions and 222 deletions

View File

@@ -36,7 +36,6 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _AIO_H
#define _AIO_H
@@ -160,6 +159,7 @@ struct aiocb {
* - EINVAL the starting position of the file is past the maximum offset
* for this file.
* - EINVAL aiocbp is a NULL pointer
* - EINVAL aiocbp->sigevent is not valid.
*/
int aio_read(
struct aiocb *aiocbp
@@ -178,6 +178,7 @@ int aio_read(
* - EINVAL invalid aio_reqprio or aio_offset or aio_nbytes
* - EAGAIN not enough memory
* - EINVAL aiocbp is a NULL pointer
* - EINVAL aiocbp->sigevent is not valid.
*/
int aio_write(
struct aiocb *aiocbp
@@ -213,7 +214,6 @@ int aio_error(
const struct aiocb *aiocbp
);
/**
* @brief Retrieve Return Status of Asynchronous I/O Operation
*
@@ -284,6 +284,7 @@ int aio_suspend(
* - EINVAL A value of op other than O_SYNC was specified.
* The current implemetation only supports O_SYNC.
* - EINVAL aiocbp is a NULL pointer.
* - EINVAL aiocbp->sigevent is not valid.
*/
int aio_fsync(
int op,

View File

@@ -41,14 +41,18 @@
#ifndef _AIO_MISC_H
#define _AIO_MISC_H
#include <stdio.h>
#include <string.h>
#include <signal.h>
#include <aio.h>
#include <pthread.h>
#include <rtems.h>
#include <rtems/chain.h>
#include <rtems/seterr.h>
#ifdef RTEMS_DEBUG
#include <stdio.h>
#endif
#ifdef __cplusplus
extern "C" {
#endif
@@ -190,6 +194,17 @@ int rtems_aio_remove_req(
struct aiocb *aiocbp
);
/**
* @brief Checks the validity of a sigevent struct
*
* Checks if the pointer passed as parameter points to a valid sigevent struct.
*
* @param sigp Is a pointer to the sigevent struct to check.
* @retval 0 The struct is not valid.
* @retval 1 The struct is valid.
*/
int rtems_aio_check_sigevent( struct sigevent *sigp );
#ifdef RTEMS_DEBUG
#include <assert.h>

View File

@@ -36,7 +36,6 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
@@ -76,7 +75,7 @@ int aio_cancel( int fildes, struct aiocb *aiocbp )
return AIO_ALLDONE;
}
AIO_printf ( "Request chain on [IQ]\n" );
AIO_printf( "Request chain on [IQ]\n" );
rtems_chain_extract( &r_chain->next_fd );
rtems_aio_remove_fd( r_chain );

View File

@@ -59,6 +59,9 @@ int aio_fsync(
if ( op != O_SYNC )
rtems_set_errno_and_return_minus_one( EINVAL );
if ( rtems_aio_check_sigevent( &aiocbp->aio_sigevent ) == 0 )
rtems_set_errno_and_return_minus_one( EINVAL );
mode = fcntl( aiocbp->aio_fildes, F_GETFL );
if (

View File

@@ -42,7 +42,9 @@
#include <stdlib.h>
#include <unistd.h>
#include <time.h>
#include <signal.h>
#include <rtems/posix/aio_misc.h>
#include <rtems/score/assert.h>
#include <errno.h>
/**
@@ -82,6 +84,31 @@ static void rtems_aio_insert_prio(
rtems_aio_request *req
);
/**
* @brief Wrapper for pthread_create() call.
*
* This function serves as a wrapper with the appropriate signature for a call
* to pthread_create(). It receives a pointer to a sigevent structure that
* contains a pointer to the function to be called and the parameters to be
* passed to it.
*
* @param args Pointer to the sigevent struct containing a pointer to the
* function and its parameters.
* @return void*
*/
static void *rtems_aio_notify_function_wrapper( void *args );
/**
* @brief Generates a notification.
*
* The signal is generated using a sigevent struct, as defined from the
* POSIX specifications.
*
* @param sigp is a pointer to the sigevent struct that will be used
* to generate the signal
*/
static void rtems_aio_notify( struct sigevent *sigp );
rtems_aio_queue aio_request_queue;
int rtems_aio_init( void )
@@ -253,10 +280,8 @@ int rtems_aio_remove_req( rtems_chain_control *chain, struct aiocb *aiocbp )
return AIO_CANCELED;
}
int
rtems_aio_enqueue( rtems_aio_request *req )
int rtems_aio_enqueue( rtems_aio_request *req )
{
rtems_aio_request_chain *r_chain;
rtems_chain_control *chain;
pthread_t thid;
@@ -358,9 +383,100 @@ rtems_aio_enqueue( rtems_aio_request *req )
return 0;
}
int rtems_aio_check_sigevent( struct sigevent *sigp )
{
_Assert( sigp != NULL );
switch ( sigp->sigev_notify ) {
case SIGEV_NONE:
break;
case SIGEV_SIGNAL:
if ( sigp->sigev_signo < 1 && sigp->sigev_signo > 32 ) {
return 0;
}
break;
case SIGEV_THREAD:
if ( sigp->sigev_notify_function == NULL ) {
return 0;
}
break;
default:
return 0;
}
return 1;
}
static void *rtems_aio_notify_function_wrapper( void *args )
{
struct sigevent *sig = ( struct sigevent * ) args;
void (*notify_function)( union sigval ) = sig->sigev_notify_function;
union sigval param = ( union sigval ) sig->sigev_value;
notify_function( param );
pthread_exit( NULL );
}
static void rtems_aio_notify( struct sigevent *sigp )
{
#ifdef RTEMS_POSIX_API
int result;
#ifndef RTEMS_DEBUG
(void) result;
#endif
_Assert( sigp != NULL );
switch ( sigp->sigev_notify ) {
case SIGEV_SIGNAL:
result = sigqueue(
getpid(),
sigp->sigev_signo,
sigp->sigev_value
);
_Assert( result == 0 );
break;
case SIGEV_THREAD:
pthread_t thread;
pthread_attr_t attr;
pthread_attr_t *attrp = sigp->sigev_notify_attributes;
if ( attrp == NULL ) {
attrp = &attr;
result = pthread_attr_init( attrp );
_Assert( result == 0 );
result = pthread_attr_setdetachstate(
attrp,
PTHREAD_CREATE_DETACHED
);
_Assert( result == 0 );
}
result = pthread_create(
&thread,
attrp,
rtems_aio_notify_function_wrapper,
sigp
);
_Assert( result == 0 );
break;
}
#else
(void) sigp;
#endif
}
static void *rtems_aio_handle( void *arg )
{
rtems_aio_request_chain *r_chain = arg;
rtems_aio_request *req;
rtems_chain_control *chain;
@@ -525,6 +641,8 @@ static void rtems_aio_handle_helper( rtems_aio_request *req )
result = -1;
}
rtems_aio_notify( &req->aiocbp->aio_sigevent );
if ( result < 0 ) {
req->aiocbp->return_value = -1;
req->aiocbp->error_code = errno;

View File

@@ -71,6 +71,9 @@ int aio_read( struct aiocb *aiocbp )
if ( aiocbp->aio_offset < 0 )
rtems_set_errno_and_return_minus_one( EINVAL );
if ( rtems_aio_check_sigevent( &aiocbp->aio_sigevent ) == 0 )
rtems_set_errno_and_return_minus_one( EINVAL );
req = malloc( sizeof( rtems_aio_request ) );
if ( req == NULL )
rtems_set_errno_and_return_minus_one( EAGAIN );

View File

@@ -45,8 +45,7 @@
#include <stdlib.h>
#include <limits.h>
int
aio_write( struct aiocb *aiocbp )
int aio_write( struct aiocb *aiocbp )
{
rtems_aio_request *req;
int mode;
@@ -69,6 +68,9 @@ aio_write( struct aiocb *aiocbp )
if ( aiocbp->aio_offset < 0 )
rtems_set_errno_and_return_minus_one( EINVAL );
if ( rtems_aio_check_sigevent( &aiocbp->aio_sigevent ) == 0 )
rtems_set_errno_and_return_minus_one( EINVAL );
req = malloc( sizeof( rtems_aio_request ) );
if ( req == NULL )
rtems_set_errno_and_return_minus_one( EAGAIN );

View File

@@ -61,6 +61,8 @@ links:
uid: psxaio02
- role: build-dependency
uid: psxaio03
- role: build-dependency
uid: psxaio04
- role: build-dependency
uid: psxalarm01
- role: build-dependency

View File

@@ -0,0 +1,20 @@
SPDX-License-Identifier: CC-BY-SA-4.0 OR BSD-2-Clause
build-type: test-program
cflags: []
copyrights:
- Copyright (C) 2024 Alessandro Nardin <ale.daluch@gmail.com>
cppflags: []
cxxflags: []
enabled-by:
- RTEMS_POSIX_API
features: c cprogram
includes: []
ldflags: []
links: []
source:
- testsuites/psxtests/psxaio04/init.c
stlib: []
target: testsuites/psxtests/psxaio04.exe
type: build
use-after: []
use-before: []

View File

@@ -37,7 +37,6 @@
#include <aio.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <sched.h>
#include <fcntl.h>
@@ -61,13 +60,14 @@ struct aiocb *create_aiocb( int fd )
aiocbp->aio_offset = 0;
aiocbp->aio_reqprio = 0;
aiocbp->aio_fildes = fd;
aiocbp->aio_sigevent.sigev_notify = SIGEV_NONE;
return aiocbp;
}
void free_aiocb( struct aiocb *aiocbp )
{
free ((char*) aiocbp->aio_buf);
free (aiocbp);
free( (void*) aiocbp->aio_buf );
free( aiocbp );
}
void *POSIX_Init( void *argument )

View File

@@ -32,7 +32,7 @@
#include <errno.h>
#include <sched.h>
void *POSIX_Init (void *argument);
void *POSIX_Init( void *argument );
/* configuration information */
@@ -42,7 +42,7 @@ void *POSIX_Init (void *argument);
#define CONFIGURE_MAXIMUM_TASKS 20
#define CONFIGURE_MAXIMUM_SEMAPHORES 20
#define CONFIGURE_MAXIMUM_MESSAGE_QUEUES 20
#define CONFIGURE_MAXIMUM_FILE_DESCRIPTORS 20
#define CONFIGURE_MAXIMUM_FILE_DESCRIPTORS 20
#define CONFIGURE_INITIAL_EXTENSIONS RTEMS_TEST_INITIAL_EXTENSION
@@ -50,8 +50,8 @@ void *POSIX_Init (void *argument);
#define CONFIGURE_MAXIMUM_POSIX_KEYS 10
#define CONFIGURE_POSIX_INIT_THREAD_TABLE
#define CONFIGURE_EXTRA_TASK_STACKS (10 * RTEMS_MINIMUM_STACK_SIZE)
#define CONFIGURE_POSIX_INIT_THREAD_STACK_SIZE (10 * RTEMS_MINIMUM_STACK_SIZE)
#define CONFIGURE_EXTRA_TASK_STACKS ( 10 * RTEMS_MINIMUM_STACK_SIZE )
#define CONFIGURE_POSIX_INIT_THREAD_STACK_SIZE ( 10 * RTEMS_MINIMUM_STACK_SIZE )
#include <rtems/confdefs.h>

View File

@@ -37,7 +37,6 @@
#include <aio.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <sched.h>
#include <fcntl.h>
#include <rtems/chain.h>
@@ -45,38 +44,35 @@
const char rtems_test_name[] = "PSXAIO 2";
/* forward declarations to avoid warnings */
struct aiocb *create_aiocb(int fd);
void free_aiocb(struct aiocb *aiocbp);
struct aiocb *create_aiocb( int fd );
void free_aiocb( struct aiocb *aiocbp );
#define BUFSIZE 32
#define FD_COUNT 10
#define WRONG_FD 666
struct aiocb *
create_aiocb (int fd)
struct aiocb *create_aiocb( int fd )
{
struct aiocb *aiocbp;
aiocbp = malloc (sizeof (struct aiocb));
memset (aiocbp, 0, sizeof (struct aiocb));
aiocbp->aio_buf = malloc (BUFSIZE * sizeof (char));
aiocbp = malloc( sizeof( struct aiocb ) );
memset( aiocbp, 0, sizeof( struct aiocb ) );
aiocbp->aio_buf = malloc( BUFSIZE * sizeof( char ) );
aiocbp->aio_nbytes = BUFSIZE;
aiocbp->aio_offset = 0;
aiocbp->aio_reqprio = 0;
aiocbp->aio_fildes = fd;
aiocbp->aio_sigevent.sigev_notify = SIGEV_NONE;
return aiocbp;
}
void
free_aiocb (struct aiocb *aiocbp)
void free_aiocb( struct aiocb *aiocbp )
{
free ((char*) aiocbp->aio_buf);
free (aiocbp);
free( (void*) aiocbp->aio_buf );
free( aiocbp );
}
void *
POSIX_Init (void *argument)
void *POSIX_Init( void *argument )
{
int fd[FD_COUNT];
struct aiocb *aiocbp[FD_COUNT+1];
@@ -84,123 +80,111 @@ POSIX_Init (void *argument)
char filename[BUFSIZE];
struct sched_param param;
status = rtems_aio_init ();
rtems_test_assert (status == 0);
status = rtems_aio_init();
rtems_test_assert( status == 0 );
param.sched_priority = 30;
status = pthread_setschedparam (pthread_self(), policy, &param);
rtems_test_assert (status == 0);
status = pthread_setschedparam(
pthread_self(),
policy, &param
);
rtems_test_assert( status == 0 );
status = mkdir ("/tmp", S_IRWXU);
rtems_test_assert (!status);
status = mkdir( "/tmp", S_IRWXU );
rtems_test_assert( !status );
TEST_BEGIN();
puts ("Init: Open files");
puts( "Init: Open files" );
for (i=0; i<FD_COUNT; i++)
for( i=0; i<FD_COUNT; i++ )
{
sprintf (filename, "/tmp/aio_fildes%d",i);
fd[i] = open (filename, O_RDWR|O_CREAT, S_IRWXU|S_IRWXG|S_IRWXO);
rtems_test_assert ( fd[i] != -1);
sprintf( filename, "/tmp/aio_fildes%d", i );
fd[i] = open(
filename,
O_RDWR|O_CREAT,
S_IRWXU|S_IRWXG|S_IRWXO
);
rtems_test_assert( fd[i] != -1 );
}
puts ("Init: [WQ] aio_write on 1st file");
aiocbp[0] = create_aiocb (fd[0]);
status = aio_write (aiocbp[0]);
rtems_test_assert (status != -1);
aiocbp[0] = create_aiocb( fd[0] );
status = aio_write( aiocbp[0] );
rtems_test_assert( status != -1 );
puts ("Init: [WQ] aio_write on 2nd file");
aiocbp[1] = create_aiocb (fd[1]);
status = aio_write (aiocbp[1]);
rtems_test_assert (status != -1);
aiocbp[1] = create_aiocb( fd[1] );
status = aio_write( aiocbp[1] );
rtems_test_assert( status != -1 );
puts ("Init: [WQ] aio_read on 2nd file add by priority");
aiocbp[2] = create_aiocb (fd[1]);
status = aio_read (aiocbp[2]);
rtems_test_assert (status != -1);
aiocbp[2] = create_aiocb( fd[1] );
status = aio_read( aiocbp[2] );
rtems_test_assert( status != -1 );
puts ("Init: [WQ] aio_write on 3rd file");
aiocbp[3] = create_aiocb (fd[2]);
status = aio_write (aiocbp[3]);
rtems_test_assert (status != -1);
aiocbp[3] = create_aiocb( fd[2] );
status = aio_write( aiocbp[3] );
rtems_test_assert( status != -1 );
puts ("Init: [WQ] aio_write on 4th file");
aiocbp[4] = create_aiocb (fd[3]);
status = aio_write (aiocbp[4]);
rtems_test_assert (status != -1);
aiocbp[4] = create_aiocb( fd[3] );
status = aio_write( aiocbp[4] );
rtems_test_assert( status != -1 );
puts ("Init: [WQ] aio_write on 5th file -- [WQ] full");
aiocbp[5] = create_aiocb (fd[4]);
status = aio_write (aiocbp[5]);
rtems_test_assert (status != -1);
aiocbp[5] = create_aiocb( fd[4] );
status = aio_write( aiocbp[5] );
rtems_test_assert( status != -1 );
puts ("Init: [IQ] aio_write on 6th file");
aiocbp[6] = create_aiocb (fd[5]);
status = aio_write (aiocbp[6]);
rtems_test_assert (status != -1);
aiocbp[6] = create_aiocb( fd[5] );
status = aio_write( aiocbp[6] );
rtems_test_assert( status != -1 );
puts ("Init: [IQ] aio_write on 7th file");
aiocbp[7] = create_aiocb (fd[6]);
status = aio_write (aiocbp[7]);
rtems_test_assert (status != -1);
aiocbp[7] = create_aiocb( fd[6] );
status = aio_write( aiocbp[7] );
rtems_test_assert( status != -1 );
puts ("Init: [IQ] aio_read on 7th file add by priority");
aiocbp[8] = create_aiocb (fd[6]);
status = aio_read (aiocbp[8]);
rtems_test_assert (status != -1);
aiocbp[8] = create_aiocb( fd[6] );
status = aio_read( aiocbp[8] );
rtems_test_assert( status != -1 );
puts ("Init: [WQ] aio_sync on 1st file add by priority");
aiocbp[9] = create_aiocb (fd[0]);
status = aio_fsync (O_SYNC, aiocbp[9]);
rtems_test_assert (status != -1);
aiocbp[9] = create_aiocb( fd[0] );
status = aio_fsync( O_SYNC, aiocbp[9] );
rtems_test_assert( status != -1 );
puts ("Init: [NONE] aio_cancel aiocbp=NULL and invalid fildes");
status = aio_cancel (WRONG_FD, NULL);
rtems_test_assert (status == -1);
status = aio_cancel( WRONG_FD, NULL );
rtems_test_assert( status == -1 );
puts ("Init: [NONE] aio_cancel aiocbp=NULL valid fildes not in queue");
status = aio_cancel (fd[7], NULL);
rtems_test_assert (status == AIO_ALLDONE);
status = aio_cancel( fd[7], NULL );
rtems_test_assert( status == AIO_ALLDONE );
puts ("Init: [WQ] aio_cancel aiocbp=NULL fildes=fd[1]");
status = aio_cancel (fd[1], NULL);
rtems_test_assert (status == AIO_CANCELED);
status = aio_cancel( fd[1], NULL );
rtems_test_assert( status == AIO_CANCELED );
puts ("Init: [IQ] aio_cancel aiocbp=NULL fildes=fd[6]");
status = aio_cancel (fd[6], NULL);
rtems_test_assert (status == AIO_CANCELED);
status = aio_cancel( fd[6], NULL );
rtems_test_assert( status == AIO_CANCELED );
puts ("Init: [NONE] aio_cancel aiocbp->aio_fildes != fildes");
status = aio_cancel (fd[4],aiocbp[4]);
rtems_test_assert (status == -1 );
status = aio_cancel( fd[4], aiocbp[4] );
rtems_test_assert( status == -1 );
puts ("Init: [NONE] aio_cancel FD on [IQ], aiocb not on chain");
aiocbp[10] = create_aiocb (fd[9]);
status = aio_cancel (fd[9], aiocbp[10]);
rtems_test_assert (status == -1);
aiocbp[10] = create_aiocb( fd[9] );
status = aio_cancel( fd[9], aiocbp[10] );
rtems_test_assert( status == -1 );
puts ("Init: [IQ] aio_cancel 6th file only one request");
status = aio_cancel (fd[5], aiocbp[6]);
rtems_test_assert (status == AIO_CANCELED);
status = aio_cancel( fd[5], aiocbp[6] );
rtems_test_assert( status == AIO_CANCELED );
puts ("Init: [WQ] aio_cancel 1st file only one request");
status = aio_cancel (fd[0], aiocbp[9]);
rtems_test_assert (status == AIO_CANCELED);
status = aio_cancel( fd[0], aiocbp[9] );
rtems_test_assert( status == AIO_CANCELED );
puts ("Init: [NONE] aio_cancel empty [IQ]");
status = aio_cancel (fd[5], aiocbp[6]);
rtems_test_assert (status == AIO_ALLDONE);
status = aio_cancel( fd[5], aiocbp[6] );
rtems_test_assert( status == AIO_ALLDONE );
TEST_END();
for (i = 0; i < FD_COUNT; i++)
for ( i = 0; i < FD_COUNT; i++ )
{
close (fd[i]);
free_aiocb (aiocbp[i]);
close( fd[i] );
free_aiocb( aiocbp[i] );
}
free_aiocb (aiocbp[i]);
rtems_test_exit (0);
free_aiocb( aiocbp[i] );
rtems_test_exit( 0 );
return NULL;

View File

@@ -1,22 +1,2 @@
*** POSIX AIO TEST 02 ***
Init: Open files
Init: [WQ] aio_write on 1st file
Init: [WQ] aio_write on 2nd file
Init: [WQ] aio_read on 2nd file add by priority
Init: [WQ] aio_write on 3rd file
Init: [WQ] aio_write on 4th file
Init: [WQ] aio_write on 5th file -- [WQ] full
Init: [IQ] aio_write on 6th file
Init: [IQ] aio_write on 7th file
Init: [IQ] aio_read on 7th file add by priority
Init: [WQ] aio_sync on 1st file add by priority
Init: [NONE] aio_cancel aiocbp=NULL and invalid fildes
Init: [NONE] aio_cancel aiocbp=NULL valid fildes not in queue
Init: [WQ] aio_cancel aiocbp=NULL fildes=fd[1]
Init: [IQ] aio_cancel aiocbp=NULL fildes=fd[6]
Init: [NONE] aio_cancel aiocbp->aio_fildes != fildes
Init: [NONE] aio_cancel FD on [IQ], aiocb not on chain
Init: [IQ] aio_cancel 6th file only one request
Init: [WQ] aio_cancel 1st file only one request
Init: [NONE] aio_cancel empty [IQ]
*** END OF POSIX AIO TEST 02 ***

View File

@@ -32,7 +32,7 @@
#include <errno.h>
#include <sched.h>
void *POSIX_Init (void *argument);
void *POSIX_Init( void *argument );
/* configuration information */
@@ -42,7 +42,7 @@ void *POSIX_Init (void *argument);
#define CONFIGURE_MAXIMUM_TASKS 20
#define CONFIGURE_MAXIMUM_SEMAPHORES 20
#define CONFIGURE_MAXIMUM_MESSAGE_QUEUES 20
#define CONFIGURE_MAXIMUM_FILE_DESCRIPTORS 20
#define CONFIGURE_MAXIMUM_FILE_DESCRIPTORS 20
#define CONFIGURE_INITIAL_EXTENSIONS RTEMS_TEST_INITIAL_EXTENSION

View File

@@ -26,7 +26,7 @@
*
*/
#if !defined(OPERATION_COUNT)
#if !defined( OPERATION_COUNT )
#define OPERATION_COUNT 100
#endif
@@ -50,38 +50,34 @@
const char rtems_test_name[] = "PSXAIO 3";
/* forward declarations to avoid warnings */
struct aiocb *create_aiocb(int fd);
void free_aiocb(struct aiocb *aiocbp);
struct aiocb *create_aiocb( int fd );
void free_aiocb( struct aiocb *aiocbp );
#define FD_COUNT 6
#define BUFSIZE 128
struct aiocb *
create_aiocb (int fd)
struct aiocb *create_aiocb( int fd )
{
struct aiocb *aiocbp;
aiocbp = malloc (sizeof (struct aiocb));
memset (aiocbp, 0, sizeof (struct aiocb));
aiocbp->aio_buf = malloc (BUFSIZE * sizeof (char));
aiocbp = malloc( sizeof( struct aiocb ) );
memset( aiocbp, 0, sizeof( struct aiocb ) );
aiocbp->aio_buf = malloc( BUFSIZE * sizeof( char ) );
aiocbp->aio_nbytes = BUFSIZE;
aiocbp->aio_offset = 0;
aiocbp->aio_reqprio = 0;
aiocbp->aio_fildes = fd;
aiocbp->aio_sigevent.sigev_notify = SIGEV_NONE;
return aiocbp;
}
void
free_aiocb (struct aiocb *aiocbp)
void free_aiocb( struct aiocb *aiocbp )
{
free ((char*) aiocbp->aio_buf);
free (aiocbp);
free( (void*) aiocbp->aio_buf );
free( aiocbp );
}
void *
POSIX_Init (void *argument)
void *POSIX_Init( void *argument )
{
int fd[FD_COUNT];
struct aiocb *aiocbp[FD_COUNT+1];
@@ -89,79 +85,74 @@ POSIX_Init (void *argument)
char filename[BUFSIZE];
struct sched_param param;
status = rtems_aio_init ();
rtems_test_assert (status == 0);
status = rtems_aio_init();
rtems_test_assert( status == 0 );
param.sched_priority = 30;
status = pthread_setschedparam (pthread_self(), policy, &param);
rtems_test_assert (status == 0);
status = pthread_setschedparam(
pthread_self(),
policy,
&param
);
rtems_test_assert( status == 0 );
status = mkdir ("/tmp", S_IRWXU);
rtems_test_assert (!status);
status = mkdir( "/tmp", S_IRWXU );
rtems_test_assert( !status );
TEST_BEGIN();
puts (" Init: Open files ");
for (i=0; i<FD_COUNT; i++)
for ( i=0; i<FD_COUNT; i++ )
{
sprintf (filename, "/tmp/aio_fildes%d",i);
fd[i] = open (filename, O_RDWR|O_CREAT, S_IRWXU|S_IRWXG|S_IRWXO);
rtems_test_assert ( fd[i] != -1);
sprintf( filename, "/tmp/aio_fildes%d",i );
fd[i] = open(
filename,
O_RDWR|O_CREAT,
S_IRWXU|S_IRWXG|S_IRWXO
);
rtems_test_assert( fd[i] != -1 );
}
puts (" Init: [WQ] aio_write on 1st file ");
aiocbp[0] = create_aiocb (fd[0]);
status = aio_write (aiocbp[0]);
rtems_test_assert (status != -1);
aiocbp[0] = create_aiocb( fd[0] );
status = aio_write( aiocbp[0] );
rtems_test_assert( status != -1 );
puts (" Init: [WQ] aio_write on 2nd file ");
aiocbp[1] = create_aiocb (fd[1]);
status = aio_write (aiocbp[1]);
rtems_test_assert (status != -1);
aiocbp[1] = create_aiocb( fd[1] );
status = aio_write( aiocbp[1] );
rtems_test_assert( status != -1 );
puts (" Init: [WQ] aio_read on 2nd file add by priority ");
aiocbp[2] = create_aiocb (fd[1]);
status = aio_read (aiocbp[2]);
rtems_test_assert (status != -1);
aiocbp[2] = create_aiocb( fd[1] );
status = aio_read( aiocbp[2] );
rtems_test_assert( status != -1 );
puts (" Init: [WQ] aio_write on 3rd file ");
aiocbp[3] = create_aiocb (fd[2]);
status = aio_write (aiocbp[3]);
rtems_test_assert (status != -1);
aiocbp[3] = create_aiocb( fd[2] );
status = aio_write( aiocbp[3] );
rtems_test_assert( status != -1 );
puts (" Init: [WQ] aio_write on 4th file ");
aiocbp[4] = create_aiocb (fd[3]);
status = aio_write (aiocbp[4]);
rtems_test_assert (status != -1);
aiocbp[4] = create_aiocb( fd[3] );
status = aio_write( aiocbp[4] );
rtems_test_assert( status != -1 );
puts (" Init: [WQ] aio_write on 5th file -- [WQ] full ");
aiocbp[5] = create_aiocb (fd[4]);
status = aio_write (aiocbp[5]);
rtems_test_assert (status != -1);
aiocbp[5] = create_aiocb( fd[4] );
status = aio_write( aiocbp[5] );
rtems_test_assert( status != -1 );
puts (" Init: [IQ] aio_write on 6th file ");
aiocbp[6] = create_aiocb (fd[5]);
status = aio_read (aiocbp[6]);
rtems_test_assert (status != -1);
aiocbp[6] = create_aiocb( fd[5] );
status = aio_read( aiocbp[6] );
rtems_test_assert( status != -1 );
puts (" Init: going to sleep for 5 sec ");
sleep (5);
puts (" Init: going to sleep again for 5 sec ");
sleep (5);
puts (" Init: going to sleep again for 5 sec ");
sleep (5);
sleep( 5 );
sleep( 5 );
sleep( 5 );
TEST_END();
for (i = 0; i < FD_COUNT; i++)
for( i = 0; i < FD_COUNT; i++ )
{
close (fd[i]);
free_aiocb (aiocbp[i]);
close( fd[i] );
free_aiocb( aiocbp[i] );
}
free_aiocb (aiocbp[i]);
rtems_test_exit (0);
free_aiocb( aiocbp[i] );
rtems_test_exit( 0 );
return NULL;
}

View File

@@ -1,13 +1,2 @@
*** POSIX AIO TEST 03 ***
Init: Open files
Init: [WQ] aio_write on 1st file
Init: [WQ] aio_write on 2nd file
Init: [WQ] aio_read on 2nd file add by priority
Init: [WQ] aio_write on 3rd file
Init: [WQ] aio_write on 4th file
Init: [WQ] aio_write on 5th file -- [WQ] full
Init: [IQ] aio_write on 6th file
Init: going to sleep for 5 sec
Init: going to sleep again for 5 sec
Init: going to sleep again for 5 sec
*** END OF POSIX AIO TEST 03 ***

View File

@@ -16,7 +16,7 @@
#include <errno.h>
#include <sched.h>
void *POSIX_Init (void *argument);
void *POSIX_Init( void *argument );
/* configuration information */
@@ -26,7 +26,7 @@ void *POSIX_Init (void *argument);
#define CONFIGURE_MAXIMUM_TASKS 10
#define CONFIGURE_MAXIMUM_SEMAPHORES 10
#define CONFIGURE_MAXIMUM_MESSAGE_QUEUES 10
#define CONFIGURE_MAXIMUM_FILE_DESCRIPTORS 10
#define CONFIGURE_MAXIMUM_FILE_DESCRIPTORS 10
#define CONFIGURE_INITIAL_EXTENSIONS RTEMS_TEST_INITIAL_EXTENSION
@@ -34,8 +34,8 @@ void *POSIX_Init (void *argument);
#define CONFIGURE_MAXIMUM_POSIX_KEYS 10
#define CONFIGURE_POSIX_INIT_THREAD_TABLE
#define CONFIGURE_EXTRA_TASK_STACKS (5 * RTEMS_MINIMUM_STACK_SIZE)
#define CONFIGURE_POSIX_INIT_THREAD_STACK_SIZE (5 * RTEMS_MINIMUM_STACK_SIZE)
#define CONFIGURE_EXTRA_TASK_STACKS ( 5 * RTEMS_MINIMUM_STACK_SIZE )
#define CONFIGURE_POSIX_INIT_THREAD_STACK_SIZE ( 5 * RTEMS_MINIMUM_STACK_SIZE )
#include <rtems/confdefs.h>

View File

@@ -0,0 +1,151 @@
/* SPDX-License-Identifier: BSD-2-Clause */
/*
* Copyright 2024, Alessandro Nardin <ale.daluch@gmail.com>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#define CONFIGURE_INIT
#include "system.h"
#include <rtems.h>
#include "tmacros.h"
#include <rtems/posix/aio_misc.h>
#include <aio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sched.h>
#include <fcntl.h>
#include <signal.h>
const char rtems_test_name[] = "PSXAIO 4";
#define BUFSIZE 512
#define WRONG_FD 404
/* forward declarations to avoid warnings */
struct aiocb *create_aiocb( int fd );
void free_aiocb( struct aiocb *aiocbp );
void notify( union sigval sig );
struct aiocb *create_aiocb( int fd )
{
struct aiocb *aiocbp;
aiocbp = malloc( sizeof( struct aiocb ) );
memset( aiocbp, 0, sizeof( struct aiocb ) );
aiocbp->aio_buf = malloc( BUFSIZE * sizeof( char ) );
aiocbp->aio_nbytes = BUFSIZE;
aiocbp->aio_offset = 0;
aiocbp->aio_reqprio = 0;
aiocbp->aio_fildes = fd;
aiocbp->aio_sigevent.sigev_notify = SIGEV_NONE;
return aiocbp;
}
void free_aiocb( struct aiocb *aiocbp )
{
free( (void*) aiocbp->aio_buf );
free( aiocbp );
}
void notify( union sigval sig )
{
kill( getpid(), sig.sival_int );
}
void *POSIX_Init( void *argument )
{
int fd, status, received_signal, sig;
struct aiocb *aiocbp;
sigset_t sig_set;
sig = SIGUSR1;
rtems_aio_init();
status = mkdir( "/tmp", S_IRWXU );
rtems_test_assert( !status );
fd = open(
"/tmp/aio_fildes",
O_RDWR|O_CREAT,
S_IRWXU|S_IRWXG|S_IRWXO
);
rtems_test_assert( fd != -1 );
TEST_BEGIN();
aiocbp = create_aiocb( fd );
aiocbp->aio_sigevent.sigev_notify = SIGEV_SIGNAL;
aiocbp->aio_sigevent.sigev_signo = SIGUSR1;
status =sigemptyset( &sig_set );
rtems_test_assert( status == 0 );
status =sigaddset( &sig_set, sig );
rtems_test_assert( status == 0 );
status = sigprocmask( SIG_BLOCK, &sig_set, NULL );
rtems_test_assert( status == 0 );
status = aio_write( aiocbp );
rtems_test_assert( status == 0 );
status = sigwait( &sig_set, &received_signal );
rtems_test_assert( status == 0 );
rtems_test_assert( received_signal == sig );
aiocbp = create_aiocb( fd );
aiocbp->aio_sigevent.sigev_notify = SIGEV_THREAD;
aiocbp->aio_sigevent.sigev_notify_attributes = NULL;
aiocbp->aio_sigevent.sigev_notify_function = &notify;
aiocbp->aio_sigevent.sigev_value.sival_int = sig;
status =sigemptyset( &sig_set );
rtems_test_assert( status == 0 );
status =sigaddset( &sig_set, sig );
rtems_test_assert( status == 0 );
status = sigprocmask( SIG_BLOCK, &sig_set, NULL );
rtems_test_assert( status == 0 );
status = aio_write( aiocbp );
rtems_test_assert( status == 0 );
status = sigwait( &sig_set, &received_signal );
rtems_test_assert( status == 0 );
rtems_test_assert( received_signal == sig );
TEST_END();
close( fd );
rtems_test_exit( 0 );
return NULL;
}

View File

@@ -0,0 +1,2 @@
*** BEGIN OF TEST PSXAIO 4 ***
*** END OF TEST PSXAIO 4 ***

View File

@@ -0,0 +1,61 @@
/* SPDX-License-Identifier: BSD-2-Clause */
/*
* Copyright 2024, Alessandro Nardin <ale.daluch@gmail.com>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/* functions */
#include <pmacros.h>
#include <pthread.h>
#include <errno.h>
#include <sched.h>
void *POSIX_Init( void *argument );
/* configuration information */
#define CONFIGURE_APPLICATION_NEEDS_SIMPLE_CONSOLE_DRIVER
#define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER
#define CONFIGURE_MAXIMUM_TASKS 20
#define CONFIGURE_MAXIMUM_SEMAPHORES 20
#define CONFIGURE_MAXIMUM_MESSAGE_QUEUES 20
#define CONFIGURE_MAXIMUM_FILE_DESCRIPTORS 20
#define CONFIGURE_INITIAL_EXTENSIONS RTEMS_TEST_INITIAL_EXTENSION
#define CONFIGURE_MAXIMUM_POSIX_THREADS 10
#define CONFIGURE_MAXIMUM_POSIX_KEYS 10
#define CONFIGURE_POSIX_INIT_THREAD_TABLE
#define CONFIGURE_EXTRA_TASK_STACKS ( 10 * RTEMS_MINIMUM_STACK_SIZE )
#define CONFIGURE_POSIX_INIT_THREAD_STACK_SIZE ( 10 * RTEMS_MINIMUM_STACK_SIZE )
#include <rtems/confdefs.h>
/* global variables */
TEST_EXTERN pthread_t Init_id;
/* end of include file */