#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
#include "libmicro.h"
typedef struct {
int ts_once;
int ts_id;
int ts_us0;
int ts_us1;
int ts_them0;
int ts_them1;
} tsd_t;
static int nthreads;
#define DEFD "/private/tmp"
static char *optd = DEFD;
static int file;
static int nlocks;
int
benchmark_init()
{
lm_tsdsize = sizeof (tsd_t);
(void) sprintf(lm_optstr, "d:");
lm_defN = "cscd_fcntl";
(void) sprintf(lm_usage,
" [-d directory for temp file (default %s)]\n"
"notes: thread cascade using fcntl region locking\n",
DEFD);
return (0);
}
int
benchmark_optswitch(int opt, char *optarg)
{
switch (opt) {
case 'd':
optd = optarg;
break;
default:
return (-1);
}
return (0);
}
int
benchmark_initrun()
{
int errors = 0;
char fname[1024];
nthreads = lm_optP * lm_optT;
nlocks = nthreads * 2;
(void) sprintf(fname, "%s/cascade.%ld", optd, getpid());
file = open(fname, O_CREAT | O_TRUNC | O_RDWR, 0600);
if (file == -1) {
errors++;
}
if (unlink(fname)) {
errors++;
}
if (ftruncate(file, nlocks * 3) == -1) {
errors++;
}
return (errors);
}
int
block(int index)
{
struct flock fl;
fl.l_type = F_WRLCK;
fl.l_whence = SEEK_SET;
fl.l_start = index;
fl.l_len = 1;
return (fcntl(file, F_SETLKW, &fl) == -1);
}
int
unblock(int index)
{
struct flock fl;
fl.l_type = F_UNLCK;
fl.l_whence = SEEK_SET;
fl.l_start = index;
fl.l_len = 1;
return (fcntl(file, F_SETLK, &fl) == -1);
}
int
benchmark_initbatch(void *tsd)
{
tsd_t *ts = (tsd_t *)tsd;
int e = 0;
if (ts->ts_once == 0) {
int us, them;
#if !defined(__APPLE__)
us = (getpindex() * lm_optT) + gettindex();
#else
us = gettsdindex(tsd);
#endif
them = (us + 1) % (lm_optP * lm_optT);
ts->ts_id = us;
ts->ts_us0 = (us * 4);
ts->ts_us1 = (us * 4) + 2;
if (us < nthreads - 1) {
ts->ts_them0 = (them * 4);
ts->ts_them1 = (them * 4) + 2;
} else {
ts->ts_them0 = (them * 4) + 2;
ts->ts_them1 = (them * 4);
}
ts->ts_once = 1;
}
e += block(ts->ts_them0);
return (e);
}
int
benchmark(void *tsd, result_t *res)
{
tsd_t *ts = (tsd_t *)tsd;
int i;
int e = 0;
e += block(ts->ts_us0);
for (i = 0; i < lm_optB; i += 2) {
e += unblock(ts->ts_us0);
e += block(ts->ts_them1);
e += unblock(ts->ts_them0);
e += block(ts->ts_us1);
e += unblock(ts->ts_us1);
e += block(ts->ts_them0);
e += unblock(ts->ts_them1);
e += block(ts->ts_us0);
}
e += unblock(ts->ts_them0);
e += unblock(ts->ts_us0);
res->re_count = i;
res->re_errors = e;
return (0);
}