/*------------------------------------------------------------------------- * Filename: do_druk.c * Copyright: Copyright (C) 2001, Johan Pouwelse * Author: Johan Pouwelse (J.A.Pouwelse@its.tudelft.nl) * Description: Main file for a testing program of the clock deamon scheduler * automatically reserves processor cycles. * Created at: 1st Feb 2001 * Modified by: * Modified at: *-----------------------------------------------------------------------*/ /* * do_druk.c: main file for the clock speed scheduler tester * * Copyright (C) 2001 Johan Pouwelse (J.A.Pouwelse@its.tudelft.nl) * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ #include #include #include #include /*#include #include */ #include #include #include #include #include #include extern char *optarg; extern int optind, opterr, optopt; extern int errno; void error(const char *error) { printf("ERROR: %s.\n",error); exit(-1); } /* Write "n" bytes to a descriptor. */ ssize_t numbered_write(int fd, const void *vptr, size_t n) { size_t nleft; ssize_t nwritten; const char *ptr; ptr = vptr; nleft = n; while (nleft > 0) { if ( (nwritten = write(fd, ptr, nleft)) <= 0) { if (errno == EINTR) nwritten = 0; /* and call write() again */ else error("socket write failed"); /* error */ } nleft -= nwritten; ptr += nwritten; } return(n); } static ssize_t buffered_read(int fd, char *ptr) { static int read_cnt = 0; static char *read_ptr; static char read_buf[128]; if (read_cnt <= 0) { /* I/O buffer filled ? */ again: if ( (read_cnt = read(fd, read_buf, sizeof(read_buf))) < 0) { if (errno == EINTR) goto again; printf("reading error\n"); return(-1); /* read returned an error */ } else if (read_cnt == 0) return(0); read_ptr = read_buf; } /* todo flush buffer if data was from other socket ! */ read_cnt--; *ptr = *read_ptr++; return(1); } /* read bytes from the given socket until \n encoutered or ^D */ ssize_t line_read(int fd, void *vptr, size_t maxlen) { int n, rc; char c, *ptr; ptr = vptr; for (n = 1; n < maxlen; n++) { if ( (rc = buffered_read(fd, &c)) == 1) { *ptr++ = c; if (c == '\n') break; /* newline is stored, like fgets() */ } else if (rc == 0) { if (n == 1) return(0); /* EOF, no data read */ else break; /* EOF, some data was read */ } else error("socket read error"); /* error, errno set by read() */ } *ptr = 0; /* null terminate like fgets() */ return(n); } /* create a listen socket at the specified port. */ /* returns only a valid socket fd, exits with error() in case of */ /* failure. */ int create_socket(int port) { int sock, code; struct sockaddr_un servaddr; if ( (sock=socket(AF_LOCAL, SOCK_STREAM, 0)) < 0) { error("could not create socket"); } bzero(&servaddr, sizeof(servaddr)); servaddr.sun_family = AF_LOCAL; strcpy(servaddr.sun_path, "/tmp/clockd.sock"); if ((code=connect(sock, &servaddr, sizeof(servaddr))) < 0) { printf("connect error code %d.\n",errno); if (errno==ENETUNREACH) printf("network unreachable\n"); if (errno==ECONNREFUSED) printf("connection refused\n"); error("no connect to server"); } return(sock); } void h262_scenario(void) { static int sock; int x; static char mesg[96]; struct timeval waiter; /* start at frame 134; 5-6-10 is with the event time after: 7 */ int schedule[16]={8, 2, 11, 0, 5, 4, 4, 5, 6, 10, 10, 6, 6, 5, 5,5}; sock=create_socket(6666); for(x=0;x<16;x++) { sprintf(mesg,"task speed=%d start=%d deadline=%d\r\n",schedule[x]+4,x*66666,(x+1)*66666); numbered_write(sock,mesg,strlen(mesg)); } sprintf(mesg,"task speed=2 start=%d deadline=%d\r\n",7*66666+25000,7*66666+25000+150000); numbered_write(sock,mesg,strlen(mesg)); for(x=0;x<17;x++) { line_read(sock,mesg,strlen("clock scheduler>\n")); printf("CLOCKD %16.16s.\n",mesg); } waiter.tv_usec=0; waiter.tv_sec=1; select(0,NULL,NULL,NULL,&waiter); /* wait the specified number of u_sec */ for(x=0;x<16;x++) { sprintf(mesg,"time advance=%d\r\n",66666); numbered_write(sock,mesg,strlen(mesg)); line_read(sock,mesg,strlen("clock scheduler>\n")); printf("CLOCKD %16.16s.\n",mesg); waiter.tv_usec=66666; waiter.tv_sec=0; select(0,NULL,NULL,NULL,&waiter); /* wait the specified number of u_sec */ } waiter.tv_usec=0; waiter.tv_sec=2; select(0,NULL,NULL,NULL,&waiter); /* wait the specified number of u_sec */ close(sock); } void h262_scenario_old(void) { int sock; char mesg[256]; struct timeval waiter; sock=create_socket(6666); sprintf(mesg,"task speed=9 deadline=6700000 start=0\r\n"); numbered_write(sock,mesg,strlen(mesg)); /* send request */ sprintf(mesg,"task speed=10 deadline=13300000 start=6700000\r\n"); numbered_write(sock,mesg,strlen(mesg)); /* send request */ sprintf(mesg,"task speed=14 deadline=20000000 start=13300000\r\n"); numbered_write(sock,mesg,strlen(mesg)); /* send request */ sprintf(mesg,"task speed=3 deadline=17500000 start=2500000\r\n"); numbered_write(sock,mesg,strlen(mesg)); /* send request */ waiter.tv_usec=30000000; waiter.tv_sec=0; select(0,NULL,NULL,NULL,&waiter); /* wait the specified number of u_sec */ close(sock); } int main(int argc, char **argv) { int option, sock; int amount=1, duration=10000000, wait=0, wait2=0, speed=1, port=6666, nodeadline=0, killing=0; struct timeval busy, waiter; /* wait a specified amount of time */ while ((option=getopt(argc,argv,"2na:d:w:s:p:hk")) >= 0) { switch(option) { case 'a': amount=atoi(optarg); break; case 'd': duration=atoi(optarg); break; case '2': h262_scenario(); exit(0); break; case 'w': wait=atoi(optarg); /* only start any action after 'wait' u_sec */ wait2=atoi(optarg); /* remember this value */ waiter.tv_usec=wait%1000000; wait-=waiter.tv_usec; waiter.tv_sec=wait/1000000; break; case 's': speed=atoi(optarg); break; case 'n': nodeadline=1; break; case 'k': killing=1; break; case 'p': port=atoi(optarg); break; case 'h': printf("be busy and send commands to a clock scheduler\n"); printf("USAGE: -a the amount of requests to scheduler, default=1\n"); printf(" -d time in u_sec of 1 request, default=10 seconds\n"); printf(" -w start after waiting u_sec, default=0\n"); printf(" -s the requested speed at the interval, default=1\n"); printf(" -p change default port number, default=6666\n"); printf(" -k kill the daemon afterwards\n"); printf(" -2 execute the 3 frame H.263 emulation scenario\n"); printf(" -n Special mode that does NOT send deadline to daemon\n"); printf(" The start time is also NOT send\n"); exit(0); default: printf("Unknown optind: %d, ARG1: %s.\n", optind, optarg); } } sock=create_socket(port); if (wait>0 && nodeadline==0) select(0,NULL,NULL,NULL,&waiter); /* wait the specified number of u_sec */ gettimeofday(&busy,(struct timezone *)NULL); /* current time in busy */ printf("%06ld.%06ld\t-1\tDO_DRUK_START\n", busy.tv_sec,busy.tv_usec); waiter.tv_usec=duration%1000000; /* split the duration time */ duration-=waiter.tv_usec; waiter.tv_sec=duration/1000000; if (busy.tv_usec + waiter.tv_usec >= 1000000) { /* calculate the time until we keep busy */ busy.tv_sec+=waiter.tv_sec+1; /* add the 1 sec due to the u_sec overflow */ busy.tv_usec+=waiter.tv_usec-1000000; } else { busy.tv_sec+=waiter.tv_sec; busy.tv_usec+=waiter.tv_usec; } while(1) { /* keep busy */ gettimeofday(&waiter,(struct timezone *)NULL); /* current time in waiter */ if( waiter.tv_sec >= busy.tv_sec && waiter.tv_usec >= busy.tv_usec) break; } printf("%06ld.%06ld\t-1\tDO_DRUK_DONE\n", waiter.tv_sec,waiter.tv_usec); waiter.tv_usec=0; waiter.tv_sec=3; select(0,NULL,NULL,NULL,&waiter); /* wait the specified number of u_sec */ close(sock); return(0); }