NetBSD-5.0.2/regress/sys/kern/lockf/lockf.c

Compare this file to the similar file:
Show the results in this format:

/*	$NetBSD: lockf.c,v 1.7 2008/04/28 20:23:07 martin Exp $	*/

/*-
 * Copyright (c) 2000 The NetBSD Foundation, Inc.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

/*
 * lockf regression test:
 *
 * Tests:
 * 1) fork N child processes, do a bunch of random byte range lock/unlock.
 */

#include <sys/types.h>
#include <sys/wait.h>
#include <sys/ptrace.h> 

#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <err.h>
#include <signal.h>
#include <errno.h>

int nlocks = 1000;		/* number of locks per thread */
int nprocs = 10;		/* number of processes to spawn */
int sleeptime = 500000;		/* sleep time between locks, usec */
off_t size = 8192;		/* size of file to lock */
const char *lockfile = "/tmp/lockf_test";

static u_int32_t
random_uint32(void)
{
	return lrand48();
}


static void
trylocks(int id)
{
	int i, ret, fd;
	const char *which = NULL;
	
	srand48(getpid());

	fd = open (lockfile, O_RDWR, 0);
	
	if (fd < 0)
		err(1, lockfile);
	
	printf("%d: start\n", id);
	
	for (i=0; i<nlocks; i++) {
		struct flock fl;

		fl.l_start = random_uint32() % size;
		fl.l_len = random_uint32() % size;
		switch (random_uint32() % 3) {
		case 0:
			which = "read";
			fl.l_type = F_RDLCK;
			break;
		case 1:
			which = "write";
			fl.l_type = F_WRLCK;
			break;
		case 2:
			which = "un";
			fl.l_type = F_UNLCK;
			break;
		}
		fl.l_whence = SEEK_SET;

		printf("%d: try %slock %d to %d\n", id, which, (int)fl.l_start,
		    (int)(fl.l_start + fl.l_len));
		
		ret = fcntl(fd, F_SETLKW, &fl);

		if (ret < 0)
			perror("fcntl");
		printf("%d: got %slock %d to %d\n", id, which, (int)fl.l_start,
		    ((int)(fl.l_start + fl.l_len)));
		
		if (usleep(sleeptime) < 0) 
		  err(1, "usleep");
	}
	printf("%d: done\n", id);
	close (fd);
}

/* ARGSUSED */
int
main(int argc, char **argv)
{
	int i, j;
	pid_t *pid;
	int status;
	int fd;
	
	(void)unlink(lockfile);

	fd = open (lockfile, O_RDWR|O_CREAT|O_EXCL|O_TRUNC, 0666);
	if (fd < 0)
		err(1, "%s", lockfile);

	if (ftruncate(fd, size) < 0)
		err(1, "ftruncate of %s failed", lockfile);

	fsync(fd);
	close(fd);
	
	pid = malloc(nprocs * sizeof(pid_t));
	
	for (i=0; i<nprocs; i++) {
		pid[i] = fork();
		switch (pid[i]) {
		case 0:
			trylocks(i);
			_exit(0);
			break;
		case -1:
			err(1, "fork failed");
			break;
		default:
			break;
		}
	}
	for (j=0; j<100; j++) {
		printf("parent: run %i\n", j+1);
		for (i=0; i<nprocs; i++) {
			printf("stop %d\n", i);
			if (ptrace(PT_ATTACH, pid[i], 0, 0) < 0)
				err(1, "ptrace attach %d", pid[i]);
			printf("wait %d\n", i);
			if (waitpid(pid[i], &status, WUNTRACED) < 0)
				err(1, "waitpid(ptrace)");
			printf("awake %d\n", i);
			usleep(sleeptime/3);
			if (ptrace(PT_DETACH, pid[i], (caddr_t)1, 0) < 0)
				err(1, "ptrace detach %d", pid[i]);
			printf("done %d\n", i);
			usleep(sleeptime/3);
		}
	}
	for (i=0; i<nprocs; i++) {
		printf("reap %d: ", i);
		fflush(stdout);
		kill(pid[i], SIGINT);
		waitpid(pid[i], &status, 0);
		printf(" status %d\n", status);
	}
	exit(0);
	/* NOTREACHED */
}