/* Reads from or writes to the given sector at bytes i such that from <= i < to, * reading them to or writing them from buffer. buffer must have size at least * from - to. * * For internal use. */ static void cached_read_write(block_sector_t sector, bool write, uint32_t from, uint32_t to, void *buffer) { ASSERT (from < to); ASSERT (to <= BLOCK_SECTOR_SIZE); struct cached_block *cb; while (true) { reader_acquire(§or_lock); cb = find_cached_sector(sector); if (cb != NULL) { reader_release(§or_lock); rw_acquire(&cb->rw_lock, write); if (cb->sector == sector && (cb->state == CLEAN || cb->state == DIRTY)) { /* Typical case: Found the sector in cache, and it didn't * change before we got a chance to see it. */ if (write) { memcpy(cb->data + from, buffer, (to - from)); cb->state = DIRTY; } else { memcpy(buffer, cb->data + from, (to - from)); } cb->accessed = true; /* XXX synchronized? */ rw_release(&cb->rw_lock, write); return; } /* Atypical case: We found the sector in cache, but it changed * before we got a chance to see it: Try again. */ rw_release(&cb->rw_lock, write); } else { cb = get_free_block(); reader_release(§or_lock); writer_acquire(§or_lock); if (find_cached_sector(sector) == NULL) { /* Typical case: We didn't find the sector in cache, and it * didn't pop up before we could add it */ cb->sector = sector; cb->state = IN_IO; writer_release(§or_lock); block_read(fs_device, cb->sector, cb->data); cb->state = CLEAN; if (write) { memcpy(cb->data + from, buffer, (to - from)); cb->state = DIRTY; } else { memcpy(buffer, cb->data + from, (to - from)); } cb->accessed = true; writer_release(&cb->rw_lock); return; } /* Atypical case: We didn't find the sector in cache, but it * popped up before we could add it: Try again. */ writer_release(§or_lock); writer_release(&cb->rw_lock); } } }
void *rw_bnchmrk(void *arg) { /* struct unpack */ struct opts o = *(struct opts*)arg; int wprob = o.prob; int *shared_array = o.array; struct rw *l = o.lock; int wcslen = o.wcslen; int rcslen = o.rcslen; int ncslen = o.ncslen; unsigned msecs = o.msecs; int node, private_array[64]; long i = 0; /* result */ struct timeval tsmain, tfmain, tsncs, tfncs, tswcs, tfwcs, tsrcs, tfrcs; int seed = time(NULL); gettimeofday(&tsmain, NULL); gettimeofday(&tfmain, NULL); while (mtimediff(tfmain, tsmain) <= msecs) { i++; gettimeofday(&tsncs, NULL); gettimeofday(&tfncs, NULL); while (mtimediff(tfncs, tsncs) <= ncslen) { int r = rand_r(&seed) % 500; private_array[rand_r(&seed) % 64] += r; private_array[rand_r(&seed) % 64] -= r; gettimeofday(&tfncs, NULL); } int p = rand_r(&seed) % 100; if( p < wprob) { gettimeofday(&tswcs, NULL); rw_acquire(l, W, &node); /*entering the critical section*/ gettimeofday(&tfwcs, NULL); while (mtimediff(tfwcs, tswcs) <= wcslen) { int r = rand_r(&seed) % 500; shared_array[rand_r(&seed) % 64] += r; shared_array[rand_r(&seed) % 64] -= r; gettimeofday(&tfwcs, NULL); } rw_release(l, W, node); } else { gettimeofday(&tsrcs, NULL); rw_acquire(l, R, &node); /*entering the critical section*/ gettimeofday(&tfrcs, NULL); while (mtimediff(tfrcs,tsrcs) <= rcslen) { volatile int i1 = shared_array[rand_r(&seed) % 64]; volatile int i2 = shared_array[rand_r(&seed) % 64]; gettimeofday(&tfrcs, NULL); } rw_release(l, R, node); } gettimeofday(&tfmain, NULL); } return (void *)i; }