Skip to content

Commit

Permalink
Added some other aio tests. Small include fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
afxgroup committed Mar 7, 2023
1 parent ad05948 commit 61cc6c5
Show file tree
Hide file tree
Showing 9 changed files with 271 additions and 15 deletions.
1 change: 1 addition & 0 deletions library/aio/aio_misc.c
Original file line number Diff line number Diff line change
Expand Up @@ -467,6 +467,7 @@ handle_fildes_io(void *arg) {
pthread_setschedparam(self, policy, &param);
}


/* Process request pointed to by RUNP. We must not be disturbed by signals. */
if ((aiocbp->aiocb.aio_lio_opcode & 127) == LIO_READ) {
if (sizeof(off_t) != sizeof(off64_t) && aiocbp->aiocb.aio_lio_opcode & 128)
Expand Down
2 changes: 1 addition & 1 deletion library/include/endian.h
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ __bswap_32 (unsigned int __bsx)
#define __BYTE_ORDER__ BYTE_ORDER
#endif

#ifndef __BYTE_ORDER__
#ifndef __BYTE_ORDER
#define __BYTE_ORDER BYTE_ORDER
#endif

Expand Down
16 changes: 4 additions & 12 deletions library/include/signal.h
Original file line number Diff line number Diff line change
Expand Up @@ -143,26 +143,18 @@ struct sigaction {

extern int sigaction(int sig, const struct sigaction *act, struct sigaction *oact);

/* Type for data associated with a signal. */
union __sigval
{
int __sival_int;
void *__sival_ptr;
};

typedef union __sigval __sigval_t;
typedef __sigval_t sigval_t;
typedef union sigval sigval_t;


struct sigevent {
union __sigval sigev_value;
union sigval sigev_value;
int sigev_signo;
int sigev_notify;
union {
char __pad[64 - 2*sizeof(int) - sizeof(union __sigval)];
char __pad[64 - 2*sizeof(int) - sizeof(union sigval)];
pid_t sigev_notify_thread_id;
struct {
void (*sigev_notify_function)(union __sigval);
void (*sigev_notify_function)(union sigval);
pthread_attr_t *sigev_notify_attributes;
} __sev_thread;
} __sev_fields;
Expand Down
1 change: 0 additions & 1 deletion library/include/unistd.h
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,6 @@ extern ssize_t pwrite64(int fd, const void *buf, size_t nbytes, off64_t offset);
long int __result = 0; \
do { \
__result = (long int)(exp); \
printf("result = %d\n", __result); \
} while ((__result == -1) && (errno == EINTR)); \
__result; \
})
Expand Down
2 changes: 1 addition & 1 deletion test_programs/aio/aio1.c
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ main(int argc, char *argv[]) {
ioList[j].aiocbp->aio_offset = 0;
ioList[j].aiocbp->aio_sigevent.sigev_notify = SIGEV_SIGNAL;
ioList[j].aiocbp->aio_sigevent.sigev_signo = IO_SIGNAL;
ioList[j].aiocbp->aio_sigevent.sigev_value.__sival_ptr = &ioList[j];
ioList[j].aiocbp->aio_sigevent.sigev_value.sival_ptr = &ioList[j];

s = aio_read(ioList[j].aiocbp);
if (s == -1)
Expand Down
43 changes: 43 additions & 0 deletions test_programs/aio/aio2.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
#include <stdio.h>
#include <string.h>
#include <aio.h>
#include <stdlib.h>
#include <fcntl.h>

#define BUFSIZE 1024

int main(void) {
int fd, ret;
struct aiocb my_aiocb;

fd = open("file.txt", O_RDONLY);
if (fd < 0)
perror("open");

bzero((char *) &my_aiocb, sizeof(struct aiocb));

my_aiocb.aio_buf = calloc(1, BUFSIZE + 1);
if (!my_aiocb.aio_buf)
perror("malloc");

my_aiocb.aio_fildes = fd;
my_aiocb.aio_nbytes = BUFSIZE;
my_aiocb.aio_offset = 0;

ret = aio_read(&my_aiocb);
if (ret < 0)
perror("aio_read");

while (aio_error(&my_aiocb) == EINPROGRESS)
continue;

if ((ret = aio_return(&my_aiocb))) {
printf("ret:%d,read:%s\n", ret, my_aiocb.aio_buf);
} else {
printf("read 0\n");
}


close(fd);
return 0;
}
162 changes: 162 additions & 0 deletions test_programs/aio/aio_client.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
#include <aio.h>
#include <stdio.h>
#include <stdlib.h>
#include <netdb.h>
#include <string.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <assert.h>
#include <errno.h>
#include <arpa/inet.h>

#define BUFSIZE (100)

#ifndef __amigaos4__
#define sigval_t __sigval_t
#endif

void aio_read_completion_handler(sigval_t sigval);
void aio_write_completion_handler(sigval_t sigval);
struct aiocb my_aiocb1, my_aiocb2;

// Global variables
struct aiocb *cblist[2];
int theSocket;

void InitializeAiocbData(struct aiocb *pAiocb, char *pBuffer) {
bzero((char *) pAiocb, sizeof(struct aiocb));

pAiocb->aio_fildes = theSocket;
pAiocb->aio_nbytes = BUFSIZE;
pAiocb->aio_offset = 0;
pAiocb->aio_buf = pBuffer;
}

void IssueReadOperation(struct aiocb *pAiocb, char *pBuffer) {
InitializeAiocbData(pAiocb, pBuffer);

/* Link the AIO request with a thread callback */
pAiocb->aio_sigevent.sigev_notify = SIGEV_THREAD;
pAiocb->aio_sigevent.sigev_notify_function = aio_read_completion_handler;
pAiocb->aio_sigevent.sigev_notify_attributes = NULL;
pAiocb->aio_sigevent.sigev_value.sival_ptr = &my_aiocb1;

int ret = aio_read(pAiocb);
assert(ret >= 0);
}

void IssueWriteOperation(struct aiocb *pAiocb, char *pBuffer) {
InitializeAiocbData(pAiocb, pBuffer);

/* Link the AIO request with a thread callback */
pAiocb->aio_sigevent.sigev_notify = SIGEV_THREAD;
pAiocb->aio_sigevent.sigev_notify_function = aio_write_completion_handler;
pAiocb->aio_sigevent.sigev_notify_attributes = NULL;
pAiocb->aio_sigevent.sigev_value.sival_ptr = &my_aiocb2;

int ret = aio_write(pAiocb);
assert(ret >= 0);
}

void aio_write_completion_handler(sigval_t sigval) {
struct aiocb *req;
req = (struct aiocb *) sigval.sival_ptr;
}

void aio_read_completion_handler(sigval_t sigval) {
struct aiocb *req;
req = (struct aiocb *) sigval.sival_ptr;
}

int main() {
int ret;
int nPort = 11111;
char *szServer = "102.168.0.204";

// Connect to the remote server
theSocket = socket(AF_INET, SOCK_STREAM, 0);
assert(theSocket >= 0);

struct hostent *pServer;
struct sockaddr_in serv_addr;
pServer = gethostbyname(szServer);

bzero((char *) &serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(nPort);
bcopy((char *) pServer->h_addr, (char *) &serv_addr.sin_addr.s_addr, pServer->h_length);

assert(connect(theSocket, (const struct sockaddr *) (&serv_addr), sizeof(serv_addr)) >= 0);

// Construct the AIO callbacks array
char *pBuffer = malloc(BUFSIZE + 1);

bzero((char *) cblist, sizeof(cblist));
cblist[0] = &my_aiocb1;
cblist[1] = &my_aiocb2;

// Start the read and write operations on the same socket
IssueReadOperation(&my_aiocb1, pBuffer);
IssueWriteOperation(&my_aiocb2, pBuffer);

// Wait for I/O completion on both operations
int nRound = 1;
printf("\naio_suspend round #%d:\n", nRound++);
ret = aio_suspend(cblist, 2, NULL);
assert(ret == 0);

// Check the error status for the read and write operations
ret = aio_error(&my_aiocb1);
assert(ret == EWOULDBLOCK);

// Get the return code for the read
{
ssize_t retcode = aio_return(&my_aiocb1);
printf("First read operation results: aio_error=%d, aio_return=%d - That's the first EWOULDBLOCK\n", ret, retcode);
}

ret = aio_error(&my_aiocb2);
assert(ret == EINPROGRESS);
printf("Write operation is still \"in progress\"\n");

// Re-issue the read operation
IssueReadOperation(&my_aiocb1, pBuffer);

// Wait for I/O completion on both operations
printf("\naio_suspend round #%d:\n", nRound++);
ret = aio_suspend(cblist, 2, NULL);
assert(ret == 0);

// Check the error status for the read and write operations for the second time
ret = aio_error(&my_aiocb1);
assert(ret == EINPROGRESS);
printf("Second read operation request is suddenly marked as \"in progress\"\n");

ret = aio_error(&my_aiocb2);
assert(ret == 0);

// Get the return code for the write
{
ssize_t retcode = aio_return(&my_aiocb2);
printf("Write operation has completed with results: aio_error=%d, aio_return=%d\n", ret, retcode);
}

// Now try waiting for the read operation to complete - it'll just busy-wait, receiving "EWOULDBLOCK" indefinitely
do {
printf("\naio_suspend round #%d:\n", nRound++);
ret = aio_suspend(cblist, 1, NULL);
assert(ret == 0);

// Check the error of the read operation and re-issue if needed
ret = aio_error(&my_aiocb1);
if (ret == EWOULDBLOCK) {
IssueReadOperation(&my_aiocb1, pBuffer);
printf("EWOULDBLOCK again on the read operation!\n");
}
} while (ret == EWOULDBLOCK);

free(pBuffer);

return 0;
}
File renamed without changes.
59 changes: 59 additions & 0 deletions test_programs/aio/aio_suspend2.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
#include <aio.h>
#include <stdio.h>

char CONTENT[] = "asdf;";
const int LENGTH = 5;

struct aiocb createIoRequest(int fd, off_t offset, volatile void *content, size_t length) {
// create and initialize the aiocb structure.
// If we don't init to 0, we have undefined behavior.
// E.g. through sigevent op.aio_sigevent there could be
// a callback function being set, that the program
// tries to call - which will then fail.
struct aiocb ret = {0};
{
ret.aio_fildes = fd;
ret.aio_offset = offset;
ret.aio_buf = content;
ret.aio_nbytes = length;
}
return ret;
}


int main() {
FILE *file = fopen("RAM:outfile.txt", "w");
int fd = fileno(file);

struct aiocb op = createIoRequest(fd, 0, CONTENT, LENGTH);
struct aiocb op2 = createIoRequest(fd, LENGTH, CONTENT, LENGTH);

// schedule write
// for valgrind mem leak output see comments from answer in
// https://stackoverflow.com/questions/4248720/aio-h-aio-read-and-write-memory-leak
int ret = aio_write(&op);
printf("aio_write 1: %d\n", ret);
ret = aio_write(&op2);
printf("aio_write 2: %d\n", ret);

// wait until everything is done

const int OPs = 2;
const struct aiocb *aiolist[OPs];
aiolist[0] = &op;
aiolist[1] = &op2;

ret = aio_suspend(aiolist, OPs, NULL);
printf("aio_suspend: %d\n", ret);

// report possible errors
ret = aio_error(&op);
printf("errno 1: %d\n", ret);
ret = aio_error(&op2);
printf("errno 2: %d\n", ret);
// error codes can be checked in <errno.h>

fclose(file);

return 0;
}

0 comments on commit 61cc6c5

Please sign in to comment.