From owner-freebsd-bugs Tue Dec 19 20:50:12 2000 From owner-freebsd-bugs@FreeBSD.ORG Tue Dec 19 20:50:01 2000 Return-Path: Delivered-To: freebsd-bugs@hub.freebsd.org Received: from freefall.freebsd.org (freefall.FreeBSD.org [216.136.204.21]) by hub.freebsd.org (Postfix) with ESMTP id 5ADFC37B400 for ; Tue, 19 Dec 2000 20:50:01 -0800 (PST) Received: (from gnats@localhost) by freefall.freebsd.org (8.11.1/8.11.1) id eBK4o1a42686; Tue, 19 Dec 2000 20:50:01 -0800 (PST) (envelope-from gnats) Resent-Date: Tue, 19 Dec 2000 20:50:01 -0800 (PST) Resent-Message-Id: <200012200450.eBK4o1a42686@freefall.freebsd.org> Resent-From: gnats-admin@FreeBSD.org (GNATS Management) Resent-To: freebsd-bugs@FreeBSD.org Resent-Reply-To: gnats-admin@FreeBSD.org, andy@silverbrook.com.au Received: from freefall.freebsd.org (freefall.FreeBSD.org [216.136.204.21]) by hub.freebsd.org (Postfix) with ESMTP id 33B1537B400 for ; Tue, 19 Dec 2000 20:40:24 -0800 (PST) Received: (from nobody@localhost) by freefall.freebsd.org (8.11.1/8.11.1) id eBK4eOq41601; Tue, 19 Dec 2000 20:40:24 -0800 (PST) (envelope-from nobody) Message-Id: <200012200440.eBK4eOq41601@freefall.freebsd.org> Date: Tue, 19 Dec 2000 20:40:24 -0800 (PST) From: andy@silverbrook.com.au Sender: nobody@FreeBSD.org To: freebsd-gnats-submit@FreeBSD.org X-Send-Pr-Version: www-1.0 Subject: misc/23679: libc_r thread scheduling sleep time mis-calculations Resent-Sender: gnats@FreeBSD.org Sender: owner-freebsd-bugs@FreeBSD.ORG Precedence: bulk X-Loop: FreeBSD.org >Number: 23679 >Category: misc >Synopsis: libc_r thread scheduling sleep time mis-calculations >Confidential: no >Severity: serious >Priority: medium >Responsible: freebsd-bugs >State: open >Quarter: >Keywords: >Date-Required: >Class: sw-bug >Submitter-Id: current-users >Arrival-Date: Tue Dec 19 20:50:00 PST 2000 >Closed-Date: >Last-Modified: >Originator: Andy Newman >Release: RELENG_4 >Organization: Silverbrook Research >Environment: FreeBSD bebop.silverbrook.com.au 4.2-STABLE FreeBSD 4.2-STABLE #0: Wed Nov 22 08:52:41 EST 2000 toor@bebop.silverbrook.com.au:/usr/obj/usr/src/sys/bebop i386 >Description: In a particular circumstance libc_r mis-calculates sleep times. The attached demonstration program shows the problem. A number of child processes are forked from a parent and then attempt to acquire a (SysV IPC) semaphore, do some work (sleep) and release the semaphore. Each child process attempts to sleep for a constant time (1 second). Building against libc produces the expected results. Building against libc_r produces differences in sleep times. The first child process sleeps for the correct time, the second for twice as long, the third for twice as long as that etc.... (powers of 2). Tracing the system calls being made shows that incorrect timeout values are being passed to poll(2) presumably via libc_r's thread scheduler. Prior to the poll(2) calls there are two gettimeofday(2) calls which is consistent with an execution path from libc_r's nanosleep() routine through to the thread scheduler. The shar achive has a test, tst.c, and a makefile. Two executables are built, tst, linked against libc, and tstp, linked against libc_r. The program is invoked with a single arg, the semaphore's "key". The program creates a sempahore and forks 8 child processes which all try to acquire it, do some work and release it. >How-To-Repeat: # This is a shell archive. Save it in a file, remove anything before # this line, and then unpack it by entering "sh file". Note, it may # create directories; files and directories will be owned by you and # have default permissions. # # This archive contains: # # tst.c # Makefile # echo x - tst.c sed 's/^X//' >tst.c << 'END-of-tst.c' X/* X * Demonstrate problems with process sleep times. X */ X X#include X#include X#include X#include X#include X#include X#include X#include X#include X#include X Xint mypid; X Xvoid child(int); Xvoid release(int, const char *); Xvoid log(const char *, ...); X Xint Xmain(int argc, char **argv) X{ X int semid; X int i; X key_t key; X unsigned int n_proc = 8; X unsigned long ulvar; X X mypid = getpid(); X X if (argc < 2) X goto usage; X if (sscanf(argv[1], "%lu", &ulvar) != 1) X goto usage; X key = (key_t)ulvar; X if (argc > 2 && sscanf(argv[2], "%u", &n_proc) != 1) X goto usage; X X if ((semid = semget(key, 1, IPC_CREAT|0600)) == -1) X err(1, "semget(create)"); X if (semctl(semid, 0, SETVAL, 0) < 0) X err(1, "semctl(SETVAL)"); X log("parent created semaphore, id = 0x%08x", semid); X X for (i = 0; i < n_proc; ++i) X child(semid); X X log("parent releasing semaphore"); X release(semid, "parent"); X X while (i-- > 0) X { X int status; X pid_t pid; X pid = wait(&status); X log("parent reaped child pid=%d, status=%0o", (int)pid, status); X } X X semctl(semid, 0, IPC_RMID, 0); X X return 0; X Xusage: X fprintf(stderr, "usage: %s semaphore-key [num_children]\n", argv[0]); X return 1; X} X Xvoid Xlog(const char *fmt, ...) X{ X va_list va; X struct timeval tv; X char buf[1024]; X X gettimeofday(&tv, NULL); X sprintf(buf, "%lu.%-6lu: ", tv.tv_sec, tv.tv_usec); X va_start(va, fmt); X vsprintf(buf+strlen(buf), fmt, va); X va_end(va); X fprintf(stderr, "%s\n", buf); X fflush(stderr); X} X Xvoid Xacquire(int semid) X{ X struct sembuf semops; X X semops.sem_num = 0; X semops.sem_op = -1; X semops.sem_flg = 0; X X log("child %d acquiring semaphore", mypid); X if (semop(semid, &semops, 1) < 0) X err(1, "acquire"); X log("child %d acquired semaphore", mypid); X} X Xvoid Xrelease(int semid, const char *who) X{ X struct sembuf semops; X X semops.sem_num = 0; X semops.sem_op = 1; X semops.sem_flg = 0; X log("%s %d releasing semaphore", who, mypid); X if (semop(semid, &semops, 1) < 0) X err(1, "release"); X log("%s %d released semaphore", who, mypid); X} X Xvoid Xwork(void) X{ X time_t t1, t2; X X log("child %d working for 1 second", mypid); X t1 = time(NULL); X sleep(1); X t2 = time(NULL); X log("child %d done working: %d elapsed", mypid, t2 - t1); X} X Xvoid Xchild(int semid) X{ X switch (fork()) X { X case -1: X err(1, "fork"); X X case 0: X mypid = getpid(); X acquire(semid); X work(); X release(semid, "child"); X log("child %d done", mypid); X _exit(0); X } X} END-of-tst.c echo x - Makefile sed 's/^X//' >Makefile << 'END-of-Makefile' Xall: tst tstp X Xtst : tst.c X cc -g -Wall -o tst tst.c X Xtstp: tst.c X cc -g -Wall -o tstp -pthread tst.c X Xclean: X rm -f tst tstp ktrace.out END-of-Makefile exit >Fix: >Release-Note: >Audit-Trail: >Unformatted: To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-bugs" in the body of the message