ping was causing 2.3m syscalls/s when messages were lost. this was due to large lock latency. i'm thinking about changing the alarm to just interval+waittime rather than to wait for all the messages. Reference: /n/atom/patch/applied/pinglocklat Date: Fri Feb 21 16:46:35 CET 2014 Signed-off-by: quanstro@quanstro.net --- /sys/src/cmd/ip/ping.c Fri Feb 21 16:43:11 2014 +++ /sys/src/cmd/ip/ping.c Fri Feb 21 16:43:11 2014 @@ -53,6 +53,7 @@ int quiet; int rcvdmsgs; int rint; +int nsecfd; ushort firstseq; vlong sum; int waittime = 5000; @@ -147,7 +148,7 @@ clean(ushort seq, vlong now, void *v) { int ttl; - Req **l, *r; + Req **l, *r, *rlost, **rr; ttl = 0; if (v) { @@ -156,6 +157,8 @@ else ttl = ((Ip6hdr *)v)->ttl; } + rlost = nil; + rr = &rlost; lock(&listlock); last = nil; for(l = &first; *l; ){ @@ -167,20 +170,27 @@ reply(r, v); } - if(now-r->time > MINUTE){ + if(now-r->time >= MINUTE){ *l = r->next; - r->rtt = now-r->time; - if(v) - r->ttl = ttl; - if(r->replied == 0) - lost(r, v); - free(r); + r->next = nil; + *rr = r; + rr = &(*rr)->next; }else{ last = r; l = &r->next; } } unlock(&listlock); + + for(; (r = rlost) != nil;){ + rlost = rlost->next; + r->rtt = now-r->time; + if(v) + r->ttl = ttl; + if(r->replied == 0) + lost(r, v); + free(r); + } } static uchar loopbacknet[IPaddrlen] = { @@ -279,7 +289,8 @@ r->seq = seq; r->next = nil; r->replied = 0; - r->time = nsec(); /* avoid early free in reply! */ +// nsecfd = bintime(nsecfd, &r->time, nil, nil); /* avoid early free in reply! */ + r->time = 1ull<<62; lock(&listlock); if(first == nil) first = r; @@ -287,7 +298,7 @@ last->next = r; last = r; unlock(&listlock); - r->time = nsec(); + nsecfd = bintime(nsecfd, &r->time, nil, nil); if(write(fd, buf, msglen) < msglen){ fprint(2, "%s: write failed: %r\n", argv0); return; @@ -310,9 +321,10 @@ sum = 0; while(lostmsgs+rcvdmsgs < nmsg){ alarm((nmsg-lostmsgs-rcvdmsgs)*interval+waittime); +// alarm(interval+waittime); n = read(fd, buf, sizeof buf); alarm(0); - now = nsec(); + nsecfd = bintime(nsecfd, &now, nil, nil); if(n <= 0){ /* read interrupted - time to go */ clean(0, now+MINUTE, nil); continue; @@ -490,7 +502,7 @@ int fd, msglen, interval, nmsg; char *ds; - nsec(); /* make sure time file is already open */ + nsecfd = bintime(-1, nil, nil, nil); fmtinstall('V', eipfmt); fmtinstall('I', eipfmt);