Skip to content

Commit

Permalink
Merge pull request #18019 from king-11/qt_sys_calls
Browse files Browse the repository at this point in the history
[GSOC] Qthread Select

[PR by @king-11 - reviewed by @krishnadey30 and @mppf; tested,merged by @mppf]

conditional compilation of `qt_select` for providing in a method to keep original task unblocked when observing for IO.

Prior to `qt_select` call `select` and block for 64ms which allows instantaneous connections to be established
without timing out.

Signed-off-by: Lakshya Singh <lakshay.singh1108@gmail.com>
  • Loading branch information
mppf committed Aug 4, 2021
2 parents 2bf652f + 6639c39 commit 1861b11
Showing 1 changed file with 57 additions and 35 deletions.
92 changes: 57 additions & 35 deletions runtime/src/qio/sys.c
Expand Up @@ -92,7 +92,10 @@

#endif


// to use qthread sys calls when available
#ifdef QTHREAD_VERSION
#include <qthread/qt_syscalls.h>
#endif

// Should be available in sys_xsi_strerror_r.c
extern int sys_xsi_strerror_r(int errnum, char* buf, size_t buflen);
Expand Down Expand Up @@ -1427,7 +1430,8 @@ err_t sys_accept(fd_t sockfd, sys_sockaddr_t* addr_out, fd_t* fd_out)

STARTING_SLOW_SYSCALL;

got = accept(sockfd, (struct sockaddr*) & addr_out->addr, &addr_len);
got = accept(sockfd, (struct sockaddr *)&addr_out->addr, &addr_len);

if( got != -1 ) {
if( addr_len > (socklen_t) sizeof(sys_sockaddr_storage_t) ) {
fprintf(stderr, "Warning: address truncated in sys_accept\n");
Expand Down Expand Up @@ -1471,7 +1475,8 @@ err_t sys_connect(fd_t sockfd, const sys_sockaddr_t* addr)

STARTING_SLOW_SYSCALL;

got = connect(sockfd, (const struct sockaddr*) & addr->addr, addr->len);
got = connect(sockfd, (const struct sockaddr *)&addr->addr, addr->len);

if( got != -1 ) {
err_out = 0;
} else {
Expand Down Expand Up @@ -1862,45 +1867,62 @@ err_t sys_socketpair(int domain, int type, int protocol, fd_t* sockfd_out_a, fd_
extern void chpl_task_yield(void);

err_t sys_select(int nfds, fd_set* readfds, fd_set* writefds, fd_set* exceptfds, struct timeval* timeout, int* nset) {

int got_nset;
err_t err_out = 0;
struct timeval deadline;
struct timeval now;
struct timeval real_timeout;
long wait_usec = 5;

if (timeout != NULL) {
gettimeofday(&deadline, NULL);
deadline.tv_sec += timeout->tv_sec;
deadline.tv_usec += timeout->tv_usec;
if (deadline.tv_usec > 1000000) {
deadline.tv_sec++;
deadline.tv_usec -= 1000000;
}
} else if (timeout->tv_sec == 0) {
if (timeout->tv_usec < wait_usec)
wait_usec = timeout->tv_usec;

struct timeval first_timeout;
struct timeval second_timeout = {0};
if(timeout != NULL) {
second_timeout = *timeout;
}

real_timeout.tv_sec = 0;
real_timeout.tv_usec = wait_usec;
first_timeout.tv_sec = 0;
// 64 milliseconds allows instantaneous connections whereas 32000 doesn't
// and is small enough to not block process for longtime
first_timeout.tv_usec = 64000;

while (1) {
// It would be nicer if the tasking layer supported a select
// call and knew to wait in the select call if no task was waiting
got_nset = select(nfds, readfds, writefds, exceptfds, &real_timeout);
if (got_nset == -1) err_out = errno; // save error
if (got_nset != 0) break; // exit loop if something happened
#ifndef CHPL_RT_UNIT_TEST
chpl_task_yield();
#endif
gettimeofday(&now, NULL);
if (now.tv_sec > deadline.tv_sec ||
(now.tv_sec == deadline.tv_sec && now.tv_usec > deadline.tv_usec))
break;
// calculate available timeout
if (timeout != NULL){
first_timeout.tv_usec = (second_timeout.tv_usec > 64000 || second_timeout.tv_sec >= 1) ? 64000 : second_timeout.tv_usec;

second_timeout.tv_usec -= first_timeout.tv_usec;
if(second_timeout.tv_usec < 0){
second_timeout.tv_sec -= 1;
second_timeout.tv_usec += 1000000;
}
}

// create new fd_sets otherwise original will be overwritten
fd_set temp_readfds, temp_writefds, temp_exceptfds;
FD_ZERO(&temp_readfds);
FD_ZERO(&temp_writefds);
FD_ZERO(&temp_exceptfds);
if(readfds != NULL)
temp_readfds = *readfds;
if(writefds != NULL)
temp_writefds = *writefds;
if(exceptfds != NULL)
temp_exceptfds = *exceptfds;

got_nset = select(nfds, &temp_readfds, &temp_writefds, &temp_exceptfds, &first_timeout);
if (got_nset == -1) err_out = errno; // save error

// check for error/success else check if first_timeout subtraced all the timeout.
if(got_nset != 0 || (timeout != NULL && second_timeout.tv_sec == 0 && second_timeout.tv_usec == 0)){
*nset = got_nset;
return err_out;
}

struct timeval* second_timeout_ptr = NULL;
if (timeout != NULL)
second_timeout_ptr = &second_timeout;

#if defined(QTHREAD_VERSION) && !defined(CHPL_RT_UNIT_TEST)
got_nset = qt_select(nfds, readfds, writefds, exceptfds, second_timeout_ptr);
#else
got_nset = select(nfds, readfds, writefds, exceptfds, second_timeout_ptr);
#endif
if (got_nset == -1) err_out = errno; // save error
*nset = got_nset;
return err_out;
}
Expand Down

0 comments on commit 1861b11

Please sign in to comment.