#include "bench.h" /* * lat_fcntl.c - file locking test * * Copyright (c) 1994 Larry McVoy. Distributed under the FSF GPL with * additional restriction that results may published only if * (1) the benchmark is unmodified, and * (2) the version in the sccsid below is included in the report. * Support for this development by Sun Microsystems is gratefully acknowledged. */ char *id = "$Id: lat_pipe.c,v 1.8 1997/06/16 05:38:58 lm Exp $\n"; #include "bench.h" struct flock lock, unlock; struct flock s1, s2; /* * Create two files, use them as a ping pong test. * Process A: * lock(1) * unlock(2) * Process B: * unlock(1) * lock(2) * Initial state: * lock is locked * lock2 is locked */ #define waiton(fd) fcntl(fd, F_SETLKW, &lock) #define release(fd) fcntl(fd, F_SETLK, &unlock) struct _state { char filename1[2048]; char filename2[2048]; int pid; int fd1; int fd2; }; void initialize(iter_t iterations, void* cookie); void benchmark(iter_t iterations, void* cookie); void cleanup(iter_t iterations, void* cookie); void procA(struct _state *state) { if (waiton(state->fd1) == -1) { perror("lock of fd1 failed\n"); cleanup(0, state); exit(1); } if (release(state->fd2) == -1) { perror("unlock of fd2 failed\n"); cleanup(0, state); exit(1); } if (waiton(state->fd2) == -1) { perror("lock of fd2 failed\n"); cleanup(0, state); exit(1); } if (release(state->fd1) == -1) { perror("unlock of fd1 failed\n"); cleanup(0, state); exit(1); } } void procB(struct _state *state) { if (release(state->fd1) == -1) { perror("unlock of fd1 failed\n"); cleanup(0, state); exit(1); } if (waiton(state->fd2) == -1) { perror("lock of fd2 failed\n"); cleanup(0, state); exit(1); } if (release(state->fd2) == -1) { perror("unlock of fd2 failed\n"); cleanup(0, state); exit(1); } if (waiton(state->fd1) == -1) { perror("lock of fd1 failed\n"); cleanup(0, state); exit(1); } } void initialize(iter_t iterations, void* cookie) { char buf[10000]; struct _state* state = (struct _state*)cookie; if (iterations) return; sprintf(state->filename1, "/tmp/lmbench-fcntl%d.1", getpid()); sprintf(state->filename2, "/tmp/lmbench-fcntl%d.2", getpid()); state->pid = 0; state->fd1 = -1; state->fd2 = -1; unlink(state->filename1); unlink(state->filename2); if ((state->fd1 = open(state->filename1, O_CREAT|O_RDWR, 0666)) == -1) { perror("create"); exit(1); } if ((state->fd2 = open(state->filename2, O_CREAT|O_RDWR, 0666)) == -1) { perror("create"); exit(1); } unlink(state->filename1); unlink(state->filename2); write(state->fd1, buf, sizeof(buf)); write(state->fd2, buf, sizeof(buf)); lock.l_type = F_WRLCK; lock.l_whence = 0; lock.l_start = 0; lock.l_len = 1; unlock = lock; unlock.l_type = F_UNLCK; if (waiton(state->fd1) == -1) { perror("lock1"); exit(1); } if (waiton(state->fd2) == -1) { perror("lock2"); exit(1); } handle_scheduler(benchmp_childid(), 0, 1); switch (state->pid = fork()) { case -1: perror("fork"); exit(1); case 0: handle_scheduler(benchmp_childid(), 1, 1); for ( ;; ) { procB(state); } default: break; } } void benchmark(iter_t iterations, void* cookie) { struct _state* state = (struct _state*)cookie; while (iterations-- > 0) { procA(state); } } void cleanup(iter_t iterations, void* cookie) { struct _state* state = (struct _state*)cookie; if (iterations) return; if (state->fd1 >= 0) close(state->fd1); if (state->fd2 >= 0) close(state->fd2); state->fd1 = -1; state->fd2 = -1; if (state->pid) { kill(state->pid, SIGKILL); waitpid(state->pid, NULL, 0); } state->pid = 0; } int main(int ac, char **av) { int c; int parallel = 1; int warmup = 0; int repetitions = -1; struct _state state; char *usage = "[-P ] [-W ] [-N ]\n"; /* * If they specified a parallelism level, get it. */ while (( c = getopt(ac, av, "P:W:N:")) != EOF) { switch(c) { case 'P': parallel = atoi(optarg); if (parallel <= 0) lmbench_usage(ac, av, usage); break; case 'W': warmup = atoi(optarg); break; case 'N': repetitions = atoi(optarg); break; default: lmbench_usage(ac, av, usage); break; } } state.pid = 0; benchmp(initialize, benchmark, cleanup, 0, parallel, warmup, repetitions, &state); micro("Fcntl lock latency", 2 * get_n()); return (0); }