/*************************************************************************** * DBS: Distributed Benchmark System * Copyright (c) 1995, 1996, 1997 Yukio Murayama * Copyright (c) 1995, 1996, 1997 Nara Institute of Science and Technology * All rights reserved. * * Permission to use, copy, modify and distribute this software and its * documentation is hereby granted, provided only with the following * conditions are satisfied: * * 1. Both the copyright notice and this permission notice appear in * all copies of the software, derivative works or modified versions, * and any portions thereof, and that both notices appear in * supporting documentation. * 2. All advertising materials mentioning features or use of this * software must display the following acknowledgement: * This product includes software developed by Nara Institute of * Science and Technology and its contributors. * 3. Neither the name of Nara Institute of Science and Technology nor * the names of its contributors may be used to endorse or promote * products derived from this software without specific prior written * permission. * * THIS SOFTWARE IS PROVIDED BY THE DEVELOPER ``AS IS'' AND NARA * INSTITUTE OF SCIENCE AND TECHNOLOGY DISCLAIMS ANY LIABILITY OF * ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF * THIS SOFTWARE. ALSO, THERE IS NO WARRANTY IMPLIED OR OTHERWISE, * NOR IS SUPPORT PROVIDED. * * Feedback of the results generated from any improvements or * extensions made to this software would be much appreciated. * Any such feedback should be sent to: * * Yukio Murayama * E-mail: * URL: * Address: Graduate School of Information Science, * Nara Institute of Science and Technology, * Takayama 8916-5, Ikoma, Nara, Japan * * Nara Institute of Science and Technology has the rights to * redistribute these changes. ***************************************************************************/ /***************************************************************** * Distributed Benchmark System * DBS Header File * $Revision: 1.25 $ * $Date: 1997/05/09 05:12:03 $ * $Author: yukio-m $ *****************************************************************/ #include #include #include #include #include #include #include #include #include #include #include #include #include #include "dbs.h" #include "dbsd.h" #include "record.h" #define INIT_RECORD() (rdp = rd->d, rd->n=0) #define INIT_RECORD2() (rdp2 = rd2->d, rd2->n=0) #define RECORD(NO,SIZE) (gettimeofday(&(rdp->tv), (struct timezone *)&tzp),\ rdp->packet_no = (NO),\ rdp->packet_size = (SIZE),\ rdp++, rd->n++) #define RECORD2(NO,SIZE) (gettimeofday(&(rdp2->tv), (struct timezone *)&tzp),\ rdp2->packet_no = (NO),\ rdp2->packet_size = (SIZE),\ rdp2++, rd2->n++) #define TIMEVAL_ADD(_TP1, _TP2) _TP1.tv_sec += _TP2.tv_sec;\ _TP1.tv_usec += _TP2.tv_usec;\ if (_TP1.tv_usec>=1000000) {\ _TP1.tv_sec+=_TP1.tv_usec/1000000;\ _TP1.tv_usec %= 1000000;\ } #define GETTIMEOFDAY(_TPP) gettimeofday(&tp, (struct timezone *)&tzp);\ tp.tv_sec = _TPP.tv_sec - tp.tv_sec;\ tp.tv_usec = _TPP.tv_usec - tp.tv_usec;\ if (tp.tv_usec < 0) {\ tp.tv_usec += 1000000;\ tp.tv_sec--;\ } #define USLEEP0(_SLEEP_) \ select(0, (fd_set *)0, (fd_set *)0, (fd_set *)0, (&(_SLEEP_))) #define USLEEP(_SLEEP_) \ (((_SLEEP_.tv_sec)>=0 && (_SLEEP_.tv_usec>=0))?(select(0, (fd_set *)0, (fd_set *)0, (fd_set *)0, (&(_SLEEP_)))):(1)) #define USLEEP2(_SLEEP_, _SLEEP_FLAG_) \ ((_SLEEP_FLAG_==1)?(select(0, (fd_set *)0, (fd_set *)0, (fd_set *)0, (&(_SLEEP_)))):(1)) #define WAIT_AT(_TPP) GETTIMEOFDAY(_TPP);\ USLEEP(tp); /* before 0.00001s */ #define WAIT_BEFORE(_TPP) gettimeofday(&tp, (struct timezone *) &tzp);\ tp.tv_sec = _TPP.tv_sec - tp.tv_sec;\ tp.tv_usec = _TPP.tv_usec - tp.tv_usec - 1000;\ if (tp.tv_usec < 0) {\ tp.tv_usec += 1000000;\ tp.tv_sec--;\ }\ USLEEP(tp); #define WAIT_UNTIL(_TPU) GETTIMEOFDAY(_TPU);\ DEBUGMSG2(3, fprintf(stderr, "A (%12d %12d)\n", tp.tv_sec, tp.tv_usec));\ while (tp.tv_sec>=0 && tp.tv_usec>=0) {\ USLEEP0(tp);\ GETTIMEOFDAY(_TPU);\ DEBUGMSG2(3, fprintf(stderr, "A (%12d %12d)\n", tp.tv_sec, tp.tv_usec));\ }\ DEBUGMSG2(3, fprintf(stderr, "A (%12d %12d)\n", tp.tv_sec, tp.tv_usec)); #define WAIT_AT2(_TPP, _TPI, _WAIT_FLAG_) if (_WAIT_FLAG_ == 1) {\ TIMEVAL_ADD(_TPP, _TPI);\ GETTIMEOFDAY(_TPP);\ USLEEP(tp);\ } static void udp_receive_timeout __P((int signo)); static void udp_send_timeout __P((int signo)); static void tcp_receive_timeout __P((int signo)); static void tcp_send_timeout __P((int signo)); void wait_at __P((struct timeval *tpp)); void alarm_at __P((struct timeval *tpp)); static sigjmp_buf env_alrm; static struct record_d *rdp; static struct record_d *rdp2; /************************************************************ * TCP SEND ************************************************************/ int tcp_send(cmd, data, rd, rd2, rt) struct dbsd_param * volatile cmd; char *data; struct record *rd; struct record *rd2; struct tcp_trace * volatile rt; { static struct timeval tp; struct timezone volatile tzp; struct timeval esleep; int i, j, s, offset, rest; int total=0; /* Total Size of sended data */ struct dbsd_traffic *traffic = cmd->traffic; int volatile timeout_flg = OFF; int volatile connect_flg = OFF; /* These are to avoid the optimization with the SPARC CPU's register window. */ struct dbsd_param * volatile * tmp = &cmd; struct tcp_trace * volatile * tmp2 = &rt; int volatile * tmp3 = & connect_flg; int volatile * tmp4 = & timeout_flg; struct timezone volatile * tmp5 = & tzp; DEBUGMSG(2, "TCP_SEND: Start.\n"); if (sigsetjmp(env_alrm, 0) == 0) { /* * Initialization */ if (signal(SIGALRM, tcp_send_timeout) == SIG_ERR) safe_exit(SIGNAL, "TCP_SEND.signal(SIGALRM)", strerror(errno)); INIT_RECORD(); INIT_RECORD2(); timeval_cp(&esleep, &cmd->start_time); alarm_at(&cmd->end_time); /* * Connection Establish */ if (cmd->connection_mode == AFTER) { if (cmd->serverflg == SERVER) { int d_len = sizeof(cmd->d_address); if ((cmd->fd = accept(cmd->sockfd, (struct sockaddr *)&cmd->d_address, &d_len)) < 0) safe_exit(ACCEPT, "TCP_SEND.accept", strerror(errno)); RECORD2(0,0); connect_flg = ON; setaddr(cmd->fd, &cmd->assosiation); close(cmd->sockfd); if (cmd->tcp_trace == ON) { init_so_debug(rt, &cmd->assosiation, TA_INPUT, cmd->connection_mode); DEBUGMSG(3, "INIT_SO_DEBUG: Normal END\n"); } } else if (cmd->serverflg == CLIENT) { WAIT_BEFORE(cmd->start_time); WAIT_AT(cmd->start_time); /* WAIT_UNTIL(cmd->start_time);*/ alarm_at(&cmd->end_time); RECORD2(0,0); if (connect(cmd->fd, (struct sockaddr *)&cmd->d_address, sizeof(cmd->d_address)) < 0) { DEBUGMSG2(1, perror("connect")); safe_exit(CONNECT, "TCP_SEND.connect", strerror(errno)); } RECORD2(0,0); connect_flg = ON; setaddr(cmd->fd, &cmd->assosiation); if (cmd->tcp_trace == ON) { init_so_debug(rt, &cmd->assosiation, TA_OUTPUT, cmd->connection_mode); DEBUGMSG(3, "INIT_SO_DEBUG: Normal END\n"); } } else { DEBUGMSG(1, "DBSD: tcp_send error\n"); safe_exit(INTERNALERROR, "TCP_SEND", ""); } } else { connect_flg = ON; WAIT_BEFORE(cmd->start_time); WAIT_AT(cmd->start_time); /* WAIT_UNTIL(cmd->start_time);*/ alarm_at(&cmd->end_time); } /* * Send Main Loop */ if (cmd->traffic_n == 1 && traffic->size == traffic->packet && traffic->isleep_flag == 0 && traffic->esleep_flag == 0) { if (cmd->tcp_trace != ON) { s = traffic[0].size; for (j=1; j <= cmd->send_times; j++) { if (send(cmd->fd, data, s, 0) != s) goto send_end; RECORD(total, s); total += s; } } else { s = traffic[0].size; for (j=1; j <= cmd->send_times; j++) { if (send(cmd->fd, data, s, 0) != s) goto send_end; RECORD(total, s); total += s; record_tcp_trace(rt, &cmd->assosiation, TA_OUTPUT); } } } else { for (j=1; j <= cmd->send_times; j++) { for (i=0, traffic=cmd->traffic; i < cmd->traffic_n; i++, traffic++) { for (offset=0, rest=traffic->size; rest > 0; offset+=traffic->packet, rest-=traffic->packet) { s = MIN(traffic->packet, rest); if (send(cmd->fd, data + offset, s, 0) != traffic->packet) goto send_end; /* ? */ RECORD(total, s); total += s; if (cmd->tcp_trace == ON) record_tcp_trace(rt, &cmd->assosiation, TA_OUTPUT); } USLEEP2(traffic->isleep, traffic->isleep_flag); WAIT_AT2(esleep, traffic->esleep, traffic->esleep_flag); } } } } else { DEBUGMSG(1, "*Time Out!*\n"); timeout_flg = ON; } send_end: /* * Data Transfer End */ if (connect_flg == OFF) { DEBUGMSG(1, "DBSD: connection error\n"); safe_exit(ABNORMAL, "Connection Error.", ""); } if (cmd->connection_mode == AFTER && timeout_flg == OFF) { RECORD2(0,0); close(cmd->fd); RECORD2(0,0); } alarm(0); wait_at(&cmd->end_time); sleep(END_TIME_OFFSET1); if (cmd->tcp_trace == ON) { if (cmd->connection_mode == BEFORE) record_tcp_trace2(rt, &cmd->assosiation, TA_OUTPUT); else record_tcp_trace(rt, &cmd->assosiation, TA_OUTPUT); } else if (cmd->tcp_trace == AFTER) { if (cmd->serverflg == CLIENT) init_so_debug(rt, &cmd->assosiation, TA_OUTPUT, cmd->connection_mode); else init_so_debug(rt, &cmd->assosiation, TA_INPUT, cmd->connection_mode); record_tcp_trace(rt, &cmd->assosiation, TA_OUTPUT); } if (cmd->connection_mode == BEFORE || timeout_flg == ON) { if (cmd->serverflg == SERVER) sleep(END_TIME_OFFSET2); close(cmd->fd); } DEBUGMSG(2, "TCP_SEND: Now END.\n"); return timeout_flg; } /************************************************************ * TCP RECEIVE ************************************************************/ int tcp_recv(cmd, data, rd, rd2, rt) struct dbsd_param * volatile cmd; char *data; struct record *rd; struct record *rd2; struct tcp_trace * volatile rt; { static struct timeval tp; struct timezone tzp; struct timeval esleep; int i, rest, offset, o, r, rr, total_rest, s; int total=0; /* Total Size of sended data */ struct dbsd_traffic *traffic = cmd->traffic; int volatile timeout_flg = OFF; int volatile connect_flg = OFF; /* These are to avoid the optimization with the SPARC CPU's register window. */ struct dbsd_param * volatile * tmp = &cmd; struct tcp_trace * volatile * tmp2 = &rt; int volatile * tmp3 = & connect_flg; int volatile * tmp4 = & timeout_flg; struct timezone volatile * tmp5 = & tzp; DEBUGMSG(2, "TCP_RECV: Start.\n"); if (sigsetjmp(env_alrm, 0) == 0) { /* * Initialization */ if (signal(SIGALRM, tcp_receive_timeout) == SIG_ERR) safe_exit(SIGNAL, "TCP_RECEIVE.signal(SIGALRM)", strerror(errno)); total_rest = cmd->total_size; INIT_RECORD(); INIT_RECORD2(); timeval_cp(&esleep, &cmd->start_time); WAIT_BEFORE(cmd->start_time); WAIT_AT(cmd->start_time); /* WAIT_UNTIL(cmd->start_time);*/ alarm_at(&cmd->end_time); /* * Connection Establish */ if (cmd->connection_mode == AFTER) { if (cmd->serverflg == SERVER) { int d_len = sizeof(cmd->d_address); if ((cmd->fd = accept(cmd->sockfd, (struct sockaddr *)&cmd->d_address, &d_len)) < 0) { DEBUGMSG2(1, perror("accept")); safe_exit(ACCEPT, "TCP_RECEIVE.accept", strerror(errno)); } RECORD2(0,0); connect_flg = ON; setaddr(cmd->fd, &cmd->assosiation); close(cmd->sockfd); if (cmd->tcp_trace == ON) { init_so_debug(rt, &cmd->assosiation, TA_INPUT, cmd->connection_mode); DEBUGMSG(3, "INIT_SO_DEBUG: Normal END\n"); } } else if (cmd->serverflg == CLIENT) { RECORD2(0,0); if (connect(cmd->fd, (struct sockaddr *)&cmd->d_address, sizeof(cmd->d_address)) < 0) { DEBUGMSG2(1, perror("connect")); safe_exit(CONNECT, "TCP_RECEIVE.connect", strerror(errno)); } RECORD2(0,0); connect_flg = ON; setaddr(cmd->fd, &cmd->assosiation); if (cmd->tcp_trace == ON) { init_so_debug(rt, &cmd->assosiation, TA_OUTPUT, cmd->connection_mode); DEBUGMSG(3, "INIT_SO_DEBUG: Normal END\n"); } } else { safe_exit(INTERNALERROR,"TCP_RECEIVE.serverflg", ""); } } else { connect_flg = ON; } /* * Receive Main Loop */ if (cmd->recv_mode == PACKET) { if (cmd->traffic_n == 1 && traffic->size == traffic->packet && traffic->isleep_flag == 0 && traffic->esleep_flag == 0) { if (cmd->tcp_trace != ON) { while (total_rest > 0) { o = 0; rr = r = traffic[0].packet; while (r > 0) { if ((s=recv(cmd->fd, data, r, 0)) < 0) safe_exit(RECVERROR, "TCP_RECEIVE.recv", strerror(errno)); r -= s; o += s; } RECORD(total, rr); total += rr; rest -= rr; total_rest -= rr; } } else { while (total_rest > 0) { o = 0; rr = r = traffic[0].packet; while (r > 0) { if ((s=recv(cmd->fd, data, r, 0)) < 0) safe_exit(RECVERROR, "TCP_RECEIVE.recv", strerror(errno)); r -= s; o += s; } RECORD(total, rr); total += rr; rest -= rr; total_rest -= rr; record_tcp_trace(rt, &cmd->assosiation, TA_OUTPUT); } } } else { while (total_rest > 0) { for (i=0, traffic=cmd->traffic; i < cmd->traffic_n; i++, traffic++) { for (offset=0, rest=traffic->size; rest > 0; offset+=traffic->packet, rest-=traffic->packet) { rr = r = MIN(traffic->packet, rest); rr = r = MIN(total_rest, r); o = 0; while (r > 0) { if ((s=recv(cmd->fd, data + offset + o, r, 0)) < 0) safe_exit(RECVERROR, "TCP_RECEIVE.recv", strerror(errno)); r -= s; o += s; } RECORD(total, rr); total += rr; rest -= rr; total_rest -= rr; if (cmd->tcp_trace == ON) record_tcp_trace(rt, &cmd->assosiation, TA_OUTPUT); if (total_rest <= 0) goto recv_end; /* Exit All Loop */ } USLEEP2(traffic->isleep, traffic->isleep_flag); WAIT_AT2(esleep, traffic->esleep, traffic->esleep_flag); } } } } else { if (traffic->isleep_flag == 0 && traffic->esleep_flag == 0) { if (cmd->tcp_trace != ON) { i=0; total = 0; while (total_rest > 0) { if ((s=recv(cmd->fd, data, traffic[0].size, 0)) < 0) safe_exit(RECVERROR, "TCP_RECEIVE.recv", strerror(errno)); if (i < rd->size) { RECORD(total, s); i++; } total_rest -= s; total += s; } } else { i=0; total = 0; while (total_rest > 0) { if ((s=recv(cmd->fd, data, traffic[0].size, 0)) < 0) safe_exit(RECVERROR, "TCP_RECEIVE.recv", strerror(errno)); if (i < rd->size) { RECORD(total, s); i++; } total_rest -= s; total += s; record_tcp_trace(rt, &cmd->assosiation, TA_OUTPUT); } } } else { i=0; total = 0; while (total_rest > 0) { if ((s=recv(cmd->fd, data, traffic[0].size, 0)) < 0) safe_exit(RECVERROR, "TCP_RECEIVE.recv", strerror(errno)); if (i < rd->size) { RECORD(total, s); i++; } total_rest -= s; total += s; if(cmd->tcp_trace == ON) record_tcp_trace(rt, &cmd->assosiation, TA_OUTPUT); USLEEP2(traffic->isleep, traffic->isleep_flag); WAIT_AT2(esleep, traffic->esleep, traffic->esleep_flag); } } } } else { DEBUGMSG(1, "*Time Out!*\n"); timeout_flg = ON; } recv_end: /* * Data Transfer End */ if (connect_flg == OFF) safe_exit(ABNORMAL, "Connection Error.", ""); if (cmd->connection_mode == AFTER && timeout_flg == OFF) { RECORD2(0,0); close(cmd->fd); RECORD2(0,0); } alarm(0); wait_at(&cmd->end_time); sleep(END_TIME_OFFSET1); if (cmd->tcp_trace == ON) { if (cmd->connection_mode == BEFORE) record_tcp_trace2(rt, &cmd->assosiation, TA_OUTPUT); else record_tcp_trace(rt, &cmd->assosiation, TA_OUTPUT); } else if (cmd->tcp_trace == AFTER) { if (cmd->serverflg == CLIENT) init_so_debug(rt, &cmd->assosiation, TA_OUTPUT, cmd->connection_mode); else init_so_debug(rt, &cmd->assosiation, TA_INPUT, cmd->connection_mode); record_tcp_trace(rt, &cmd->assosiation, TA_OUTPUT); } if (cmd->connection_mode == BEFORE || timeout_flg == ON) { if (cmd->serverflg == SERVER) sleep(END_TIME_OFFSET2); close(cmd->fd); } DEBUGMSG(2, "TCP_RECV: Now END.\n"); return timeout_flg; } /************************************************************ * UDP SEND ************************************************************/ int udp_send(cmd, data, rd) struct dbsd_param * volatile cmd; char *data; struct record *rd; { static struct timeval tp; struct timezone tzp; struct timeval esleep; int s, i, j; int total=0; /* Total Size of sended data */ int rest, offset; struct dbsd_traffic *traffic = cmd->traffic; char *d; struct sockaddr *dest; int length; int volatile timeout_flg = OFF; /* These are to avoid the optimization with the SPARC CPU's register window. */ struct dbsd_param * volatile * tmp = &cmd; /* to allocate cmd to memory */ int volatile * tmp4 = &timeout_flg; DEBUGMSG(2, "UDP_SEND: Start.\n"); if (sigsetjmp(env_alrm, 0) == 0) { /* * Initialization */ if (signal(SIGALRM, udp_send_timeout) == SIG_ERR) safe_exit(SIGNAL, "UDP_SEND.signal(SIGALRM)", strerror(errno)); INIT_RECORD(); timeval_cp(&esleep, &cmd->start_time); dest = (struct sockaddr *)&cmd->d_address; length = sizeof(cmd->d_address); WAIT_BEFORE(cmd->start_time); WAIT_AT(cmd->start_time); /* WAIT_UNTIL(cmd->start_time); */ alarm_at(&cmd->end_time); /* * Send Main Loop */ for (j=1; j<=cmd->send_times; j++) { for (i=0, traffic=cmd->traffic; i < cmd->traffic_n; i++, traffic++) { offset = 0; rest = traffic->size; while (1) { d = data + offset; *((unsigned int *)d) = htonl(total); /* XXX UDP Packet must larger than sizeof(int), 4byte*/ while ((s = sendto(cmd->fd, d, MIN(traffic->packet, rest), 0, dest, length)) < 0) /* NULL */; RECORD(total, traffic->packet); total += traffic->packet; rest -= traffic->packet; offset += traffic->packet; if(rest <= 3) /* XXX */ break; } USLEEP2(traffic->isleep, traffic->isleep_flag); WAIT_AT2(esleep, traffic->esleep, traffic->esleep_flag); } } } else { timeout_flg = ON; DEBUGMSG(1, "*Time Out!*\n"); } /* * Data Transfer End. */ alarm(0); wait_at(&cmd->end_time); sleep(END_TIME_OFFSET1); DEBUGMSG(2, "UDP_SEND: Now END.\n"); return timeout_flg; } /************************************************************ * UDP RECEIVE ************************************************************/ int udp_recv(cmd, data, rd) struct dbsd_param * volatile cmd; char *data; struct record *rd; { static struct timeval tp; struct timezone tzp; struct timeval esleep; int i, length, offset, rest, r; int total_rest; struct dbsd_traffic *traffic = cmd->traffic; struct sockaddr *dest; int size; int volatile ii=0; int volatile timeout_flg = OFF; /* These are to avoid the optimization with the SPARC CPU's register window. */ struct dbsd_param * volatile *tmp = &cmd; /* to allocate cmd to memory */ int volatile * tmp4 = & timeout_flg; DEBUGMSG(2, "UDP_RECV: Start.\n"); if (sigsetjmp(env_alrm, 0) == 0) { /* * Initialization */ if (signal(SIGALRM, udp_receive_timeout) == SIG_ERR) safe_exit(SIGNAL, "UDP_RECEIVE.signal(SIGALRM)", strerror(errno)); dest = (struct sockaddr *)&cmd->d_address; length=sizeof(cmd->d_address); total_rest = (unsigned long)cmd->total_size; INIT_RECORD(); timeval_cp(&esleep, &cmd->start_time); alarm_at(&cmd->end_time); /* * Receive Main Loop */ while (total_rest > 0) { for (i=0; i < cmd->traffic_n; i++) { for (offset=0, rest=traffic->size; rest > 0; offset+=traffic->packet, rest-=traffic->packet) { if ((r = (int)recvfrom(cmd->fd, (char *)data + offset, traffic->packet, 0, dest, &length)) < 0) safe_exit(RECVFROM, "UDP_RECEIVE.recvfrom", strerror(errno)); RECORD(ntohl(*((unsigned int *)((char *)data + offset))), r); ii++; total_rest -= r; } USLEEP2(traffic->isleep, traffic->isleep_flag); WAIT_AT2(esleep, traffic->esleep, traffic->esleep_flag); } } } else { /* timeout_flg = ON; XXX */ /* DEBUGMSG(1, "*Time Out!*\n"); XXX */ } /* * Data Transfer End. */ alarm(0); wait_at(&cmd->end_time); sleep(END_TIME_OFFSET1); DEBUGMSG2(1, fprintf(stderr, "RECEIVE PACKET=%d\n", ii)); DEBUGMSG(2, "UDP_RECV: Now END.\n"); return timeout_flg; } /***************************************************************** * Signal Handlers *****************************************************************/ static void tcp_send_timeout(signo) int signo; { siglongjmp(env_alrm, 1); } static void tcp_receive_timeout(signo) int signo; { siglongjmp(env_alrm, 1); } static void udp_send_timeout(signo) int signo; { siglongjmp(env_alrm, 1); } static void udp_receive_timeout(signo) int signo; { siglongjmp(env_alrm, 1); } /***************************************************************** * Timer Subroutine *****************************************************************/ /* * wait at the timeval */ void wait_at(tpp) struct timeval *tpp; { static struct timeval tp; static struct timezone tzp; if (debug >= 3) { gettimeofday(&tp, &tzp); fprintf(stderr, "Current Time (%12d %12d)\n", tp.tv_sec, tp.tv_usec); fprintf(stderr, "Sleep To (%12d %12d)\n", tpp->tv_sec, tpp->tv_usec); tp.tv_sec = tpp->tv_sec - tp.tv_sec; tp.tv_usec = tpp->tv_usec - tp.tv_usec; if (tp.tv_usec < 0) { tp.tv_usec += 1000000; tp.tv_sec--; } fprintf(stderr, "Sleep Time (%12d %12d)\n", tp.tv_sec, tp.tv_usec); USLEEP(tp); gettimeofday(&tp, &tzp); fprintf(stderr, "Waked Up At (%12d %12d)\n", tp.tv_sec, tp.tv_usec); } else { gettimeofday(&tp, &tzp); tp.tv_sec = tpp->tv_sec - tp.tv_sec; tp.tv_usec = tpp->tv_usec - tp.tv_usec; if (tp.tv_usec < 0) { tp.tv_usec += 1000000; tp.tv_sec--; } USLEEP(tp); } } /* * alarm set at the timeval */ void alarm_at(tpp) struct timeval *tpp; { static struct timeval tp; static struct timezone tzp; gettimeofday(&tp, &tzp); DEBUGMSG2(3, fprintf(stderr, "Current Time (%12d %12d)\n", tp.tv_sec, tp.tv_usec)); tp.tv_sec = tpp->tv_sec - tp.tv_sec; tp.tv_usec = tpp->tv_usec - tp.tv_usec; if (tp.tv_usec < 0) { tp.tv_usec += 1000000; tp.tv_sec--; } DEBUGMSG2(3, fprintf(stderr, "Alarm Set (%12d %12d)\n", tpp->tv_sec, tpp->tv_usec)); if (tp.tv_sec >= 0) { alarm(tp.tv_sec + 1); } }