Ejemplo n.º 1
0
/**
 * Precreate data for workers
 */
int prepare_data(void *db) {
  int i;
  for (i=0; i<WORKLOAD; i++) {
    int j;
    void *rec = wg_create_record(db, REC_SIZE);
    if(rec == NULL) {
      fprintf(stderr, "Failed to create data record #%d: skipping tests.\n", i);
      return -1;
    }
    for(j=0; j<REC_SIZE; j++) {
      if(wg_set_int_field(db, rec, j, 0) != 0) {
        fprintf(stderr,
          "Failed to create data record #%d: skipping tests.\n", i);
        return -1;
      }
    }
  }
  return 0;
}
Ejemplo n.º 2
0
void run_workers(void *db, int rcnt, int wcnt) {
  pt_data *pt_table;
  int i, tcnt;
#ifdef HAVE_PTHREAD
  int err;
  void *status;
  pthread_attr_t attr;
#endif

#if !defined(HAVE_PTHREAD) && !defined(_WIN32)
  fprintf(stderr, "No thread support: skipping tests.\n");
  return;
#endif

#ifdef HAVE_PTHREAD
  pthread_attr_init(&attr);
  pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
#endif

#if defined(BENCHMARK) && defined(HAVE_PTHREAD)
  pthread_rwlock_init(&rwlock, NULL);
#endif

#ifdef SYNC_THREADS
#if defined(HAVE_PTHREAD)
  pthread_mutex_init(&twait_mutex, NULL);
  pthread_cond_init(&twait_cv, NULL);
#elif defined(_WIN32)
  /* Manual reset event, initial state nonsignaled. */
  twait_ev = CreateEvent(NULL, TRUE, FALSE, NULL);
#endif
#endif

  tcnt = rcnt + wcnt;
  pt_table = (pt_data *) malloc(tcnt * sizeof(pt_data));
  if(!pt_table) {
    fprintf(stderr, "Failed to allocate thread table: skipping tests.\n");
    return;
  }

  /* Spawn the threads */
#ifdef SYNC_THREADS
  twait_cnt = 0;
#endif
  for(i=0; i<tcnt; i++) {
    pt_table[i].db = db;
    pt_table[i].threadid = i;

    /* First wcnt threads are writers, the remainder readers */
    if(i<wcnt) {
#if defined(HAVE_PTHREAD)
      err = pthread_create(&pt_table[i].pth, &attr, writer_thread, \
        (void *) &pt_table[i]);
#elif defined(_WIN32)
      pt_table[i].hThread = CreateThread(NULL, 0,
        (LPTHREAD_START_ROUTINE) writer_thread,
        (LPVOID) &pt_table[i], 0, NULL);
#endif
    } else {
#if defined(HAVE_PTHREAD)
      err = pthread_create(&pt_table[i].pth, &attr, reader_thread, \
        (void *) &pt_table[i]);
#elif defined(_WIN32)
      pt_table[i].hThread = CreateThread(NULL, 0,
        (LPTHREAD_START_ROUTINE) reader_thread,
        (LPVOID) &pt_table[i], 0, NULL);
#endif
    }

#if defined(HAVE_PTHREAD)
    if(err) {
      fprintf(stderr, "Error code from pthread_create: %d.\n", err);
#elif defined(_WIN32)
    if(!pt_table[i].hThread) {
      /* XXX: GetLastError() gives the error code if needed */
      fprintf(stderr, "CreateThread failed.\n");
#endif
      goto workers_done;
    }
  }

#ifdef SYNC_THREADS
  /* Check that all workers have entered wait state */
  for(;;) {
    /* While reading a word from memory is atomic, we
     * still use the mutex because we want to guarantee
     * that the last thread has called pthread_cond_wait().
     * With Win32 API, condition variables with similar
     * functionality are available starting from Windows Vista,
     * so this implementation uses a simple synchronization
     * event instead. This causes small, probably non-relevant
     * loss in sync accuracy.
     */
#ifdef HAVE_PTHREAD
    pthread_mutex_lock(&twait_mutex);
#endif
    if(twait_cnt >= tcnt) break;
#ifdef HAVE_PTHREAD
    pthread_mutex_unlock(&twait_mutex);
#endif
  }

  /* Now wake up all threads */
#if defined(HAVE_PTHREAD)
  pthread_cond_broadcast(&twait_cv);
  pthread_mutex_unlock(&twait_mutex);
#elif defined(_WIN32)
  SetEvent(twait_ev);
#endif
#endif /* SYNC_THREADS */

  /* Join the workers (wait for them to complete) */
  for(i=0; i<tcnt; i++) {
#if defined(HAVE_PTHREAD)
    err = pthread_join(pt_table[i].pth, &status);
    if(err) {
      fprintf(stderr, "Error code from pthread_join: %d.\n", err);
      break;
    }
#elif defined(_WIN32)
    WaitForSingleObject(pt_table[i].hThread, INFINITE);
    CloseHandle(pt_table[i].hThread);
#endif
  }

workers_done:
#ifdef HAVE_PTHREAD
  pthread_attr_destroy(&attr);
#endif

#if defined(BENCHMARK) && defined(HAVE_PTHREAD)
  pthread_rwlock_destroy(&rwlock);
#endif

#ifdef SYNC_THREADS
#if defined(HAVE_PTHREAD)
  pthread_mutex_destroy(&twait_mutex);
  pthread_cond_destroy(&twait_cv);
#elif defined(_WIN32)
  CloseHandle(twait_ev);
#endif
#endif
  free(pt_table);
}

/** Writer thread
 *  Runs preconfigured number of basic write transactions
 */

worker_t writer_thread(void * threadarg) {
  void * db;
  int threadid, i, j, cksum;
  void *rec = NULL, *frec = NULL;

  db = ((pt_data *) threadarg)->db;
  threadid = ((pt_data *) threadarg)->threadid;

#ifdef CHATTY_THREADS
  fprintf(stdout, "Writer thread %d started.\n", threadid);
#endif

#ifdef SYNC_THREADS
  /* Increment the thread counter to inform the caller
   * that we are entering wait state.
   */
#ifdef HAVE_PTHREAD
  pthread_mutex_lock(&twait_mutex);
#endif
  twait_cnt++;
#if defined(HAVE_PTHREAD)
  pthread_cond_wait(&twait_cv, &twait_mutex);
  pthread_mutex_unlock(&twait_mutex);
#elif defined(_WIN32)
  WaitForSingleObject(twait_ev, INFINITE);
#endif
#endif /* SYNC_THREADS */

  frec = wg_get_first_record(db);
  for(i=0; i<WORKLOAD; i++) {
    wg_int c=-1, lock_id;

#if defined(BENCHMARK) && defined(HAVE_PTHREAD)
    pthread_rwlock_wrlock(&rwlock);
#else
    /* Start transaction */
    if(!(lock_id = wg_start_write(db))) {
      fprintf(stderr, "Writer thread %d: wg_start_write failed.\n", threadid);
      goto writer_done;
    }
#endif

    /* Fetch checksum */
    cksum = wg_decode_int(db, wg_get_field(db, frec, 0));

    /* Fetch record from database */
    if(i) rec = wg_get_next_record(db, rec);
    else rec = frec;
    if(!rec) {
      fprintf(stderr, "Writer thread %d: wg_get_next_record failed.\n", threadid);
#if defined(BENCHMARK) && defined(HAVE_PTHREAD)
      pthread_rwlock_unlock(&rwlock);
#else
      wg_end_write(db, lock_id);
#endif
      goto writer_done;
    }

    /* Modify record */
    if(i) j = 0;
    else j = 1;
    for(; j<REC_SIZE; j++) {
      if (wg_set_int_field(db, rec, j, c--) != 0) {
        fprintf(stderr, "Writer thread %d: int storage error.\n", threadid);
#if defined(BENCHMARK) && defined(HAVE_PTHREAD)
        pthread_rwlock_unlock(&rwlock);
#else
        wg_end_write(db, lock_id);
#endif
        goto writer_done;
      }
    }

    /* Update checksum */
    wg_set_int_field(db, frec, 0, ++cksum);

#if defined(BENCHMARK) && defined(HAVE_PTHREAD)
    pthread_rwlock_unlock(&rwlock);
#else
    /* End transaction */
    if(!wg_end_write(db, lock_id)) {
      fprintf(stderr, "Writer thread %d: wg_end_write failed.\n", threadid);
      goto writer_done;
    }
#endif
  }

#ifdef CHATTY_THREADS
  fprintf(stdout, "Writer thread %d ended.\n", threadid);
#endif

writer_done:
#if defined(HAVE_PTHREAD)
  pthread_exit(NULL);
#elif defined(_WIN32)
  return 0;
#endif
}
Ejemplo n.º 3
0
static int op_update_record(thread_data_p tdata,void* db, void* rec, wg_int fld, wg_int value) {

  wg_set_int_field(db,rec,fld,value);
  return 0;
}