Пример #1
0
/* thread routine */
void *t_routine(void *arg)
{
    int li, sum;
    SortedListElement_t *elements = (SortedListElement_t *)arg;

    // hash and insert elements into a sublist
    for (int k = 0; k < iter_count; k++) {
        li = hash_element(&elements[k]) % list_count; //get list index

        lock_sublist(li);
        SortedList_insert(&sublist[li], &elements[k]);
        unlock_sublist(li);
    }

    // lock and enumerate all lists
    sum = 0;
    for (int k = 0; k < list_count; k++) {
        lock_sublist(k);
        sum += SortedList_length(&sublist[k]);
        unlock_sublist(k);
    }

    // hash and remove deleted 
    for (int k = 0; k < iter_count; k++) {
        li = hash_element(&elements[k]) % list_count; //get list index

        lock_sublist(li);
        SortedList_delete(SortedList_lookup(&sublist[li], elements[k].key));
        unlock_sublist(li);
    }

    return NULL;
}
Пример #2
0
void test_length()
{
	SortedList_t list;
	SortedListElement_t element[100];
	list_init(&list);

	for (int i = 0;; i++) {
		TEST_CHECK(SortedList_length(&list) == i);
		if (i >= 100)
			break;

		element_set_randkey(&element[i]);
		SortedList_insert(&list, &element[i]);
	}
}
Пример #3
0
void test_corrupt_length()
{
	SortedList_t list;
	SortedListElement_t element[100];
	list_init(&list);

	for (int i = 0; i < 100; i++) {
		element_set_randkey(&element[i]);
		SortedList_insert(&list, &element[i]);
	}

	element[99].next = element[99].prev;
	// TODO: setting to NULL causes segfault

	TEST_CHECK(SortedList_length(&list) == -1);
}
Пример #4
0
void test_delete()
{
	SortedList_t list;
	list_init(&list);

	SortedListElement_t elements[26];
	for (int i = 0; i < 26; i++) {
		char c[] = { (char)(i+97), 0 };
		element_set_key(&elements[i], c);
		SortedList_insert(&list, &elements[i]);
	}

	TEST_CHECK(SortedList_delete(&elements[25]) == 0);
	TEST_CHECK(SortedList_length(&list) == 25);
	//TEST_CHECK(is_sorted(&list));

	SortedListElement_t *e = list.next;
	while (e != &list) {
		TEST_CHECK(strcmp(e->key, elements[25].key) != 0);
		e = e->next;
	}
}
Пример #5
0
int main(int argc, char** argv){
	// for loop counter
	int i = 0;
  	// c holds return value of getopt_long
	int c;
	char* yield = NULL;
	struct timespec startTime, endTime;
	long long time_threads_create = 0;
	struct timespec starttime_threads_create, endtime_threads_create;
	  // Parse options
	while (1) {
	    int option_index = 0;
	    static struct option long_options[] = {
	// SUBCOMMAND
	   		{"iterations",       optional_argument,        0,  'i' },
        	{"threads",       optional_argument,        0,  't' },
        	{"yield",       optional_argument,        0,  'y' },
        	{"sync",		optional_argument,		0,	's'},
        	{"lists", 		optional_argument,		0,	'l'},
        	{0,0,0,0}
   		};

	    // get the next option
	    c = getopt_long(argc, argv, "", long_options, &option_index);
	   
	    // break when there are no further options to parse
	    if (c == -1)
	      	break;

	    switch (c) {
	    	//SWITCH STATEMENT
	    	case 'i':
	    		if(optarg != NULL)
	    			iterations = atoi(optarg); 
	    	break;

	    	case 't':
	    		if(optarg != NULL)
	    			nThreads = atoi(optarg);
	    	break;

	    	case 'y':
	    		if(optarg != NULL)
	    			yield= optarg;
	    		//  012345
	    			int i = 0;
	    			int run = 1;
	    			while(run){
	    				switch((int)yield[i]){
	    					case 'i':
	    						opt_yield |= INSERT_YIELD;
	    						// printf("y=insert\n");
	    						break;
	    					case 'd':
	    						opt_yield |= DELETE_YIELD;
	    						// printf("y=delte\n");
	    						break;
	    					case 's':
	    						opt_yield |= SEARCH_YIELD;
	    						// printf("y=search\n");
	    						break;
	    					default:
	    						run = 0;
	    				}
	    				i++;
	    			}
	    		break;
	    	case 's':
	    		if(optarg != NULL){
    				switch((int)optarg[0]){
    					case 'm':
    						MUTEX = 1;
    						break;
    					case 's':
    						SPIN = 1;
    						break;
	    			}
	    		}
	    		break;
	    	case 'l':
	    		if(optarg != NULL)
	    			nLists = atoi(optarg);
	    			// printf("%d\n",nLists );
		    	break;
   		}

	}

	// initialize an empty list( with dummy)
	// list = malloc(sizeof(SortedList_t**))
	list = malloc(sizeof(SortedList_t)*nLists);
	// initialize mutexes 
	if(MUTEX){
    	pthread_mutex_init(&len_mutex, NULL);
		mutex = malloc(sizeof(pthread_mutex_t) * nLists);
		for(i = 0; i != nLists; i++)	
	    	pthread_mutex_init(&(mutex[i]), NULL);
    }
    // initialize spinlocks
    if(SPIN){
    	len_spinlock = 0;
    	spinlock = malloc(sizeof(int) * nLists);

		for(i = 0; i != nLists; i++)	
	    	spinlock[i] = 0;
    }
	for(i = 0; i != nLists; i++){
		list[i].key = NULL;
		list[i].prev = &list[i];
		list[i].next = &list[i];
	}
 // 	SortedList_t l;
 // 	list = &l;
 	
	// list->key = NULL;

	// create and initializes the required number
	nElements = nThreads * iterations;
	elements = malloc(sizeof(SortedListElement_t) * nElements);
	if(elements == NULL){
		fprintf(stderr, "Error in allocating space for elements\n");
	}
	keys= malloc(sizeof(char*) * nElements);
	if(elements == NULL){
		fprintf(stderr, "Error in allocating space for keys\n");
	}
	for(i = 0; i != nElements; i++){
		int size = rand() % 15;
		keys[i] = malloc(sizeof(char) * size);
		if(keys[i] == NULL){
			fprintf(stderr, "Error in allocating space for keys[%d]\n", i);
		}
		gen_random(keys[i],size);
	}

	for(i = 0 ; i != nElements; i++){
		elements[i].key = keys[i];
		elements[i].next = NULL;
		elements[i].prev = NULL;
	}

    //create threads
    pthread_t * thread_array = malloc(sizeof(pthread_t)* nThreads);
    
    // start time
    clock_gettime(CLOCK_MONOTONIC , &startTime);



    for(i = 0; i < nThreads; i++) {
    	clock_gettime(CLOCK_MONOTONIC , &starttime_threads_create);
    	int *arg = malloc(sizeof(*arg));
    	*arg = i;
    	// measure the time it takes to create thread
		int ret = pthread_create(&thread_array[i], NULL, threadfunc, (void *) arg);  //to create thread
		clock_gettime(CLOCK_MONOTONIC , &endtime_threads_create);
	    long long startTime_ = (long long ) starttime_threads_create.tv_sec * pow(10,9) + starttime_threads_create.tv_nsec;
    	long long endTime_ = (long long ) endtime_threads_create.tv_sec * pow(10,9) + endtime_threads_create.tv_nsec;
		time_threads_create += endTime_ - startTime_;


		// printf("time_threads = %d\n", time_threads_create);
			if (ret != 0) { //error handling
				fprintf(stderr, "Error creating thread %d\n", i);
				exit(1);
			}
	}

	//wait for all to finish
	//int pthread_join(pthread_t thread, void **retval);
	//waits for thread to terminate
	for(i = 0; i < nThreads; i++) {
		int ret = pthread_join(thread_array[i], NULL);
		if (ret != 0) { //error handling
				fprintf(stderr, "Error joining thread %d\n", i);
				exit(1);
		}
	//need for loop to wait for all
	//also do error handling
	}


	// check th length of the list
	//int clock_gettime(clocked_t clk_id , struct timespec* tp) 
 	clock_gettime(CLOCK_MONOTONIC , &endTime);
	int finalLength = SortedList_length(list);
	if( finalLength != 0) {
    	fprintf(stderr, "Error! Final list length is not zero!\n");
    	exit(1);
    }

// print


    // get avarage length of a sublist.

    // int avgLen = nElements / nLists;
    long num_ops = nThreads * (iterations * 2 + 1) ;

    printf("%d threads x (%d iterations x (ins + lookup/del) + len)  = %d operations\n", nThreads, iterations,  num_ops);
    if(counter != 0){
    	fprintf(stderr, "ERROR: final count = %d\n", counter);
    }

    long long startTimel = (long long ) startTime.tv_sec * pow(10,9) + startTime.tv_nsec;
    long long endTimel = (long long ) endTime.tv_sec * pow(10,9) + endTime.tv_nsec;

    long long total_time = endTimel - startTimel;
    printf("elapsed time: %d\n", total_time);
    printf("overhead time: %d\n", time_threads_create);
    // long long avg = (total_time - time_threads_create)/ num_ops;
 	long long avg = (total_time )/ num_ops;
   
    printf("per operation: %d ns\n", avg);




  // printf("EXit with %d\n",exit_status );

    // free
    free(elements);
    for(i = 0; i != nElements; i++){
    	free(keys[i]);
    }
    free(keys);
    free(thread_array);
    free(list);
    free(spinlock);
    free(mutex);
	exit(0);


}
Пример #6
0
void* threadfunc(void* ind){
	int index = *((int*) ind);
	free(ind);
	int length;
	int i;

	// insert each element 
	for(i = 0; i < iterations; ++i) {
		int j = hash(elements[index*(iterations) + i].key);
		// printf("j=%d\n", j);
		if(MUTEX){
			int ret = pthread_mutex_lock(&(mutex[j]));
			SortedList_insert(&list[j], &elements[index*(iterations) + i]);
			// printf("releasing mutex for insert, mutex=%d\n", mutex);
			pthread_mutex_unlock(&(mutex[j]));
		}
		else if(SPIN){
			while(__sync_lock_test_and_set(&(spinlock[j]),1));
			SortedList_insert(&list[j], &elements[index*(iterations) + i]);
			// SortedList_display(list);	
			__sync_lock_release(&(spinlock[j]));
		}else{
			SortedList_insert(&list[j], &elements[index*(iterations) + i]);
		}		
	}

	// get length
	if(MUTEX){
		// lock before entering "locking" process
		pthread_mutex_lock(&len_mutex);
		for(i = 0; i != nLists; i++)
			pthread_mutex_lock(&(mutex[i]));
		
		// critical section
		length = SortedList_length(list);

		for(i = 0; i != nLists; i++)
			pthread_mutex_unlock(&(mutex[i]));
		
		pthread_mutex_unlock(&len_mutex);
	}else if(SPIN){
		// lock before entering "locking" process
		while(__sync_lock_test_and_set(&len_spinlock,1));
		
		for(i = 0; i != nLists; i++)
			while(__sync_lock_test_and_set(&(spinlock[i]),1));
		
		length = SortedList_length(list);	

		for(i = 0; i != nLists; i++)
			__sync_lock_release(&(spinlock[i]));

		__sync_lock_release(&len_spinlock);
	}else{
		length = SortedList_length(list);
	}
	// printf("length = %d\n", length);
	// look up/ delete
	for(i = 0; i < iterations; ++i) {
		int j = hash(elements[index*(iterations) + i].key);
		SortedListElement_t* target;
		if(MUTEX){
			pthread_mutex_lock(&(mutex[j])); 	
			target = SortedList_lookup(&list[j], elements[index*(iterations) + i].key);
			if(target == NULL){
				printf("should never be here.\b");
				pthread_mutex_unlock(&(mutex[j]));
				continue;
			}
			SortedList_delete(target);
			pthread_mutex_unlock(&(mutex[j]));
		}else if(SPIN){
			while(__sync_lock_test_and_set(&(spinlock[j]),1));
			target =  SortedList_lookup(&list[j], elements[index*iterations + i].key);
			if(target == NULL){
				printf("should never be here.\b");
				__sync_lock_release(&(spinlock[j]));
				continue;
			}
			SortedList_delete(target);
			__sync_lock_release(&(spinlock[j]));
		}else{
			// printf("lookup\n");
			// printf("j=%d, key=%s\n", j,elements[index*(iterations) + i].key);
			target=  SortedList_lookup(&list[j], elements[index*iterations + i].key);	
			// printf("\tDONE loopup\n");
			if(target == NULL){
				printf("should never be here.\b");
				continue;
			}
			// printf("delete\n");
			SortedList_delete(target);
			// printf("\tDONE delete\n");
		}

	}

	// SortedList_display(list);
	// length = SortedList_length(list);
}
Пример #7
0
int main(int argc, char* argv[]){

  opt_yield = 0;
  
  static struct option longOptions[] = {
    {"threads", required_argument, NULL, 't'},
    {"iterations", required_argument, NULL, 'i'},
    {"yield", required_argument, NULL, 'y'},
    {"sync", required_argument, NULL, 's'},
    {0, 0, 0, 0}
  };
  // Processes the arguments passed in
  while(1){
    int index = 0;
    int c = getopt_long(argc, argv, "", longOptions, &index);
    int i;
    if(c == -1)
      break;
    switch(c){
    case 't':
      numThreads = atoi(optarg); // atoi changes a string to a number if possible
      break;
    case 'i':
      iterations = atoi(optarg); // atoi changes a string to a number if possible
      break;
    case 's':
      // for the case of sync, we find the sync_mechanism by looking at the first character
      sync_mechanism = optarg[0];
      break;
    case 'y':
      // For the case of yield, the arguments can only be ids. Based on the argument, we set opt_yield accordingly
      for(i = 0; i < strlen(optarg); i++){
	if(optarg[i] == 'i'){
	  opt_yield |= 0x01;
	}
	else if(optarg[i] == 'd'){
	  opt_yield |= 0x02;
	}
	else if(optarg[i] == 's'){
	  opt_yield |= 0x04;
	}
	else{
	  exit(-1);
	}
      }
    }
  }

  // Initializes the linked list. We will be using a circular linked list with a dummy node
  head = (SortedList_t*) malloc(sizeof(SortedList_t));
  head->next = head;
  head->prev = head;
  char *key = 0;
  head->key = key;

  // Generates random strings of keylen characters
  int n = numThreads*iterations;
  char* keylist = (char*) malloc( (keylen + 1) * n * sizeof(char));
  int nchars = 1 + 'z' - '0';  // number of characters between 0 and z
  int counter = 0;
  for(int i = 0; i < ((keylen + 1) * n); i++){
    counter++;
    if(counter%(keylen + 1) == 0) // on the (keylen+1)th character,
      keylist[i] = 0; // set as nullbyte
    else
      keylist[i] = '0' + rand()%nchars; // random character offset from 0 in ascii
  }

  // Generates numThreads*iterations number of nodes
  SortedListElement_t *nodes = (SortedListElement_t*) malloc( n * sizeof(SortedListElement_t));
  for(int i=0; i<n; i++){
    nodes[i].key = keylist + i*(keylen + 1); // assigns a string to each node
  }

  // Dynamically creates threads based on what we passed into the threads argument
  pthread_t* tid = (pthread_t*) malloc(sizeof(pthread_t)*numThreads);
  pthread_attr_t attr;
  pthread_attr_init(&attr);
  pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
  pthread_mutex_init(&mutex, NULL);

  // collect start time
  struct timespec my_start_time;
  clock_gettime(CLOCK_MONOTONIC, &my_start_time);

  // start threads
  for(int i=0; i < numThreads; i++){
    if( pthread_create(&tid[i] , &attr, thread_function, (void*) (nodes+(i*iterations)) ) ){
      fprintf(stderr, "Error creating threads");
      exit(1);
    }
  }

  pthread_attr_destroy(&attr);

  // wait for all the threads to finish
  for(int i=0; i < numThreads; i++){
    if( pthread_join(tid[i], NULL) ){
      fprintf(stderr, "Error joining threads");
      exit(1);
    }
  }

  // collect end time
  struct timespec my_end_time;
  clock_gettime(CLOCK_MONOTONIC, &my_end_time);

  free(keylist);
  free(nodes);
  free(tid);

  // calculates the elapsed time in nanoseconds
  long long elapsed_time = (my_end_time.tv_sec - my_start_time.tv_sec) * 1000000000;
  elapsed_time += my_end_time.tv_nsec;
  elapsed_time -= my_start_time.tv_nsec;

  // Report data
  int exit_status = 0;
  int operations = numThreads * iterations * 2;
  long long time_per_operation = elapsed_time / operations;
  fprintf(stdout, "%d threads x %d iterations x (insert + lookup/delete) = %d operations\n", numThreads, iterations, operations);
  if(SortedList_length(head) != 0){
    fprintf(stderr, "List is not empty at the end\n");
    exit_status = 1;
  }
  fprintf(stdout, "elapsed time: %lld\n", elapsed_time);
  fprintf(stdout, "per operation: %lld\n", time_per_operation);
  // Exit
  exit(exit_status);
}
Пример #8
0
void* thread_function(void* arg){
  SortedListElement_t* node = (SortedListElement_t*) arg;

  // Do the insertion
  for(int i=0; i<iterations; i++){
    switch(sync_mechanism){
    case 'n':
      SortedList_insert(head, node + i);
      break;
    case 'm':
      pthread_mutex_lock(&mutex);
      SortedList_insert(head, node + i);
      pthread_mutex_unlock(&mutex);
      break;
    case 's':
      while(__sync_lock_test_and_set(&lock, 1) == 1);
      SortedList_insert(head, node + i);
      __sync_lock_release(&lock);
    default:
      break;
    }
  }

  // Get the list length
  for(int i=0; i<iterations; i++){
    switch(sync_mechanism){
    case 'n':
      SortedList_length(head);
      break;
    case 'm':
      pthread_mutex_lock(&mutex);
      SortedList_length(head);
      pthread_mutex_unlock(&mutex);
      break;
    case 's':
      while(__sync_lock_test_and_set(&lock, 1) == 1);
      SortedList_length(head);
      __sync_lock_release(&lock);
    default:
      break;
    }
  }

  // Looks up and deletes each of the keys it has previously inserted
  for(int i=0; i<iterations; i++){
    SortedListElement_t* temp;
    switch(sync_mechanism){
    case 'n':
      temp = SortedList_lookup(head, node[i].key);
      SortedList_delete(node+i);
      break;
    case 'm':
      pthread_mutex_lock(&mutex);
      temp = SortedList_lookup(head, node[i].key);
      SortedList_delete(node+i);
      pthread_mutex_unlock(&mutex);
      break;
    case 's':
      while(__sync_lock_test_and_set(&lock, 1) == 1);
      temp = SortedList_lookup(head, node[i].key);
      SortedList_delete(node+i);
      __sync_lock_release(&lock);
    default:
      break;
    }
  }
  return NULL;
}
Пример #9
0
int main(int argc, char* argv[])
{
	//iterators
	long long i;
	int j;
	//used to store the input yield string to be parsed and eventually modify the extern yield
	char *yield;
	//take parameters for options threads, iterations, yields, syncs
	opterr = 0;
	int options;
	while(1)
	{
		static struct option long_options[] =
		{
			{"threads", required_argument, 0, 't'},
			{"iterations", required_argument, 0, 'i'},
			{"yield", required_argument, 0, 'y'},
			{"sync", required_argument, 0, 's'},
			{"lists", required_argument, 0, 'l'}
		};
		
		int option_index = 0;
		options = getopt_long(argc, argv, "", long_options, &option_index);
		
		if(options == -1)
			break;
			
		switch(options)
		{
			case 0:
				break;
			case 't':
				numthreads = atoi(optarg);
				break;
			case 'i':
				numiterations = atoi(optarg);
				break;
			case 'l':
				numlists = atoi(optarg);
				break;
			case 'y':
				if(optarg)
					yield = optarg;
				else
				{
					perror("Invalid argument sent to --yield. Valid options are [--yield=ids], where any inclusion of i, d, or s is allowed");
					exit(1);
				}
				i = 0;
				int run = 1;
				while(run)
				{
					switch(yield[i])
					{
						case 'i':
							//printf("i\n");
							opt_yield |= INSERT_YIELD;
							break;
						case 'd':
							//printf("d\n");
							opt_yield |= DELETE_YIELD;
							break;
						case 's':
							//printf("s\n");
							opt_yield |= SEARCH_YIELD;
							break;
						default:
							//printf("what\n");
							run = 0;
							break;
					}
					i++;
				}
				break;
			case 's':
				if(strcmp(optarg, "m") == 0)
				{
					which_lock = 'm';
					//pthread_mutex_init(&my_mutex, NULL); //in 2C need to do for multiple lists
				}
				else if(strcmp(optarg, "s") == 0)
					which_lock = 's';
				else
				{
					perror("Invalid argument sent to --sync. Valid options are [--sync=m] and [--sync=c");
					exit(1);
				}
				break;
			case '?':
				perror("Invalid option fed. Valid options are [--threads=<numthreads>], [--iterations=<numiterations>], [--lists=<numlists>], [--yield=<X>]");
				perror("where <numthreads>, <numiterations>, <numlists> are integers and X is a string containing 'ids'.");
				exit(1);
			default:
				perror("You should never get here");
				exit(1);
		}
	}
	
	
	
	//initialize numlists empty lists heads
	head = malloc(sizeof(SortedList_t) * numlists);
	for(i = 0; i != numlists; i++)
	{
		head[i].next = &head[i];
		head[i].prev = &head[i];
		head[i].key = NULL;
	}
	

	
	//initialize arrays of locks
	if(which_lock == 'm')
	{
		my_mutex = malloc(sizeof(pthread_mutex_t) * numlists);
		for(i = 0; i != numlists; i++)
			pthread_mutex_init(&my_mutex[i], NULL);
	}
	else if(which_lock == 's')
	{
		spinlock = malloc(sizeof(int) * numlists);
	}
	else if(which_lock == 0)
	{
		//do absolutely nothing;
	}
	else
	{
		perror("which_lock should be ONLY 'm', 's', or 0. otherwise, something is wrong");
		exit(1);
	}
	
	//initialize essentially a static array of characters which the key's values will point to
	char ASCII33To126[93];
	for (i = 0; i != 93; i++)
		ASCII33To126[i] = i + 33;
	
	
	//create and initialize w/ random keys required number of list elements
	//this is equal to (number of threads) * (number of iterations)
	long long numListElements = numthreads * numiterations;
	//allocate space for each list element structure
	elements = malloc(numListElements * sizeof(SortedListElement_t));
	//allocate space for each pointer to the key for each list element structue
	keys = malloc(numListElements * sizeof(char*));
	for (i = 0; i != numListElements; i++)
	{
		//generate each key. we ARBITRARILY use a key length 10 for each
		keys[i] = malloc(sizeof(char*) * 10);
		for (j = 0; j != 10; j++)
		{
			int character = rand() % 93;
			keys[i][j] = ASCII33To126[character];
		}
		elements[i].key = keys[i];
		elements[i].next = NULL;
		elements[i].prev = NULL;
	}
	
	
	//store threads here
	pthread_t pthreadarray[numthreads];
	
	//collect start time
	struct timespec my_start_time;
	clock_gettime(CLOCK_MONOTONIC, &my_start_time);
	
	//starts threads
	for(i = 0; i != numthreads; i++)
	{
		//pass i, thread number; each will use this to get which element segment its working w/
		int ret = pthread_create(&(pthreadarray[i]), NULL, (void *) &thread_routine, (void *)i);
		if(ret != 0)
		{
			fprintf(stderr, "failed to create thread %i\n", i);
			exit(1);
		}
	}
	
	//waits for threads to quit
	for(i = 0; i != numthreads; i++)
	{
		int ret = pthread_join(pthreadarray[i], NULL);
	}
	
	//collect end time
	struct timespec my_end_time;
	clock_gettime(CLOCK_MONOTONIC, &my_end_time);
	
	//get the final length of the WHOLE LIST (sum of all sublists) and output error if size != 0
	int final_listlen = 0;
	for(i = 0; i != numlists; i++)
		final_listlen += SortedList_length(&head[i]);
	if(final_listlen != 0)
		fprintf(stderr, "ERROR: list length = %i\n", final_listlen);
	
	long long numops = numthreads*numiterations*2;
	printf("%i threads x %i iterations x (insert + lookup/delete) = %i operations\n", numthreads, numiterations, numops);
	
	//calculate the elapsed time
	long long my_elapsed_time_in_ns = (my_end_time.tv_sec - my_start_time.tv_sec) * 1000000000;
	my_elapsed_time_in_ns += my_end_time.tv_nsec;
	my_elapsed_time_in_ns -= my_start_time.tv_nsec;
	
	//report data
	printf("elapsed time: %i nanoseconds\n", my_elapsed_time_in_ns);
	printf("per operation: %g nanoseconds\n\n", (double) ( (long double) my_elapsed_time_in_ns / numops ) );
	
	//exit with proper exit code depending on if there was an error in the whole list thingy
	if(final_listlen != 0)
		exit(0);
	else
		exit(1);
}
Пример #10
0
void thread_routine(void * arg)
{	
	long long threadID = (long long) arg;
	//printf("%i\n", threadID);
	int k;
	
	
	
	//insert
	if(which_lock == 'm')
	{
		for (k = 0; k != numiterations; k++)
		{
			long long index = (threadID * numiterations) + k;
			int sublistindex = getSubListIndex(&elements[index]);
			pthread_mutex_lock(&my_mutex[sublistindex]);
			SortedList_insert(&head[sublistindex], &elements[index]);
			pthread_mutex_unlock(&my_mutex[sublistindex]);
		}
	}
	else if(which_lock == 's')
	{
		for (k = 0; k != numiterations; k++)
		{
			long long index = (threadID * numiterations) + k;
			int sublistindex = getSubListIndex(&elements[index]);
			while(__sync_lock_test_and_set(&spinlock[sublistindex], 1));
			SortedList_insert(&head[sublistindex], &elements[index]);
			__sync_lock_release(&spinlock[sublistindex]);
		}
	}
	else if(which_lock == 0)
	{
		//insert set of pre-allocated elements into shared list
		for (k = 0; k != numiterations; k++)
		{
			long long index = (threadID * numiterations) + k;
			int sublistindex = getSubListIndex(&elements[index]);
			SortedList_insert(&head[sublistindex], &elements[index]);
		}
	}
	else
	{
		perror("shouldn't get here"); exit(1);
	}
	
	
	int listlen = 0;
	//get the sum of the lengths of all sublists = the length of the ENTiRE list at THIS moment
	if(which_lock == 'm')
	{
		for(k = 0; k != numlists; k++)
		{
			pthread_mutex_lock(&my_mutex[k]);
			listlen += SortedList_length(&head[k]);
			pthread_mutex_unlock(&my_mutex[k]);
		}
	}
	else if(which_lock == 's')
	{
		for(k = 0; k != numlists; k++)
		{
			while(__sync_lock_test_and_set(&spinlock[k], 1));
			listlen += SortedList_length(&head[k]);
			__sync_lock_release(&spinlock[k]);
		}
	}
	else if(which_lock == 0)
	{
		//get list length
		for(k = 0; k != numlists; k++)
			listlen += SortedList_length(&head[k]);
	}
	else
	{
		perror("shouldn't get here"); exit(1);
	}
	
	//lookup + delete
	if(which_lock == 'm')
	{
		for(k = 0; k != numiterations; k++)
		{
			long long index = (threadID*numiterations) + k;
			int sublistindex = getSubListIndex(&elements[index]);
			pthread_mutex_lock(&my_mutex[sublistindex]);
			//looks up
			SortedListElement_t* node = SortedList_lookup(&head[sublistindex], keys[index]);
			//deletes
			int ret = SortedList_delete(node);
			pthread_mutex_unlock(&my_mutex[sublistindex]);
		}
	}
	else if(which_lock == 's')
	{
		for(k = 0; k != numiterations; k++)
		{
			SortedListElement_t* node;
			long long index = (threadID*numiterations) + k;
			int sublistindex = getSubListIndex(&elements[index]);
			while(__sync_lock_test_and_set(&spinlock[sublistindex], 1));
			//looks up
			node = SortedList_lookup(&head[sublistindex], keys[index]);
			//deletes
			int ret = SortedList_delete(node);
	
			__sync_lock_release(&spinlock[sublistindex]);
		}
	}
	else if(which_lock == 0)
	{
			//looks up and deletes each of the prior keys entered
		for(k = 0; k != numiterations; k++)
		{
			long long index = (threadID*numiterations) + k;
			int sublistindex = getSubListIndex(&elements[index]);
			//looks up
			SortedListElement_t* node = SortedList_lookup(&head[sublistindex], keys[index]);
			//deletes
			int ret = SortedList_delete(node);
		}
	}
	else
	{
		perror("shouldn't get here"); exit(1);
	}
	
	pthread_exit(NULL);
}
Пример #11
0
void *bthread(void *void_ptr) {
	struct thread_info ptr = *((struct thread_info*)void_ptr);
	size_t i = (ptr.thread_number)*(ptr.itr);
	while (i < (ptr.thread_number + 1)*(ptr.itr)) {
		if (sync_flag == '_') {
			SortedList_insert(ptr.head, &(ptr.sortedarray[i]));
		}
		else if (sync_flag == 'm') {
			pthread_mutex_lock(&mutex);
			SortedList_insert(ptr.head, &(ptr.sortedarray[i]));
			pthread_mutex_unlock(&mutex);
		}
		else if (sync_flag == 's') {
			while (__sync_lock_test_and_set(&locker, 1) == 1);
			SortedList_insert(ptr.head, &(ptr.sortedarray[i]));
			__sync_lock_release(&locker);
		}
		i++;
	}

	if (sync_flag == '_') {
		if (SortedList_length(ptr.head) < 0)
			exit(1);
	}
	else if (sync_flag == 'm') {
		pthread_mutex_lock(&mutex);
		if (SortedList_length(ptr.head) < 0)
			exit(1);
		pthread_mutex_unlock(&mutex);
	}
	else if (sync_flag == 's') {
		while (__sync_lock_test_and_set(&locker, 1) == 1);
		if (SortedList_length(ptr.head) < 0)
			exit(1);
		__sync_lock_release(&locker);
	}

	size_t j = (ptr.thread_number)*(ptr.itr);
	while (j < (ptr.thread_number + 1)*(ptr.itr)) {
		if (sync_flag == '_') {
			if (SortedList_lookup(ptr.head, ptr.sortedarray[j].key) == 0)
				exit(2);
			if (SortedList_delete(&(ptr.sortedarray[j])) == 1)
				exit(2);
		}
		else if (sync_flag == 'm') {
			pthread_mutex_lock(&mutex);
			if (SortedList_lookup(ptr.head, ptr.sortedarray[j].key) == 0)
				exit(2);
			if (SortedList_delete(&(ptr.sortedarray[j])) == 1)
				exit(2);
			pthread_mutex_unlock(&mutex);
		}
		else if (sync_flag == 's') {
			while (__sync_lock_test_and_set(&locker, 1) == 1);
			if (SortedList_lookup(ptr.head, ptr.sortedarray[j].key) == 0)
				exit(2);
			if (SortedList_delete(&(ptr.sortedarray[j])) == 1)
				exit(2);
			__sync_lock_release(&locker);
		}
		j++;
	}
	return NULL;
}
Пример #12
0
int main(int argc, char *argv[]) {
	static struct option long_options[] = {
		{ "threads", required_argument, 0, 't' },
		{ "iterations", required_argument, 0, 'i' },
		{ "yield", required_argument, 0, 'y' },
		{ "sync", required_argument, 0, 's' },
		{ 0, 0, 0, 0 }
	};

	char opt;
	unsigned int thread_count = 1;
	unsigned int iteration_count = 1;
	while ((opt = getopt_long(argc, argv, "y::s:t:i:", long_options, NULL))) {
		if (opt == -1) break;
		if (opt == 't') {
			if (optarg) thread_count = strtol(optarg, NULL, 10);
		}
		else if (opt == 'i') {
			if (optarg) iteration_count = strtol(optarg, NULL, 10);
		}
		else if (opt == 'y') {
			opt_yield = 0x00;
			for (size_t i = 0; i < strlen(optarg); i++) {
				if (optarg[i] == 'i') {
					opt_yield = 0x01 | opt_yield;
				}
				else if (optarg[i] == 'd') {
					opt_yield = 0x02 | opt_yield;
				}
				else if (optarg[i] == 'l') {
					opt_yield = 0x04 | opt_yield;
				}
				else {
					fprintf(stderr, "ERROR: incorrect yield usage. Correct usage: --yield=(i/l/d) \n");
					exit(1);
				}
			}
		}
		else if (opt == 's') {
			if (optarg) {
				if (*optarg == 'm') {
					pthread_mutex_init(&mutex, NULL);
					sync_flag = 'm';
				}
				else if (*optarg == 's') {
					sync_flag = 's';
				}
				else if (*optarg == 'c') {
					sync_flag = 'c';
				}
				else {
					fprintf(stderr, "ERROR: incorrect sync usage. Correct usage: --sync (m/s/c) \n");
					exit(1);
				}
			}
			else {
				fprintf(stderr, "ERROR: incorrect sync usage. Correct usage: --sync (m/s/c) \n");
				exit(1);
			}
		}
		else {
			fprintf(stderr, "ERROR: incorrect usage. Correct usage: ./lab2_list --threads=(num) --iterations=(num) --yield=(i/l/d) --sync=(m/s/c) \n");
			exit(1);
		}
	}

	SortedList_t *head = (SortedList_t*)malloc(sizeof(SortedList_t));
	SortedList_t temp = { head, head, NULL };
	memcpy(head, &temp, sizeof(SortedList_t));

	SortedListElement_t *sortedarray = (SortedListElement_t*)malloc(sizeof(SortedListElement_t)*(thread_count*iteration_count));
	srand(time(NULL));
	long long t = 0;
	while (t < thread_count*iteration_count) {
		char *temp_key = (char*)malloc(sizeof(char));
		*temp_key = (char)(rand() % 256);
		SortedListElement_t temp2 = { NULL, NULL, temp_key };
		memcpy(&sortedarray[t], &temp2, sizeof(SortedListElement_t));
		t++;
	}

	struct thread_info *threadi = calloc(thread_count, sizeof(struct thread_info));
	if (threadi == NULL) {
		fprintf(stderr, "ERROR: memory allocation failed. \n");
		exit(2);
	}
	char *yieldo;
	size_t threadn = 0;
	yieldo = optf();
	struct timespec start_time;
	clock_gettime(CLOCK_REALTIME, &start_time);

	while (threadn < thread_count) {
		threadi[threadn].thread_number = threadn;
		threadi[threadn].head = head;
		threadi[threadn].sortedarray = sortedarray;
		threadi[threadn].itr = iteration_count;

		int generate_res = pthread_create(&(threadi[threadn].thread_id),
			NULL,
			&bthread,
			(void*)(&threadi[threadn]));
		if (generate_res != 0)
			fprintf(stderr, "ERROR: thread creation failed. \n");
		threadn++;
	}

	threadn = 0;
	while (threadn < thread_count) {
		if (pthread_join(threadi[threadn].thread_id, NULL)) {
			fprintf(stderr, "ERROR: thread join failed. \n");
			exit(2);
		}
		threadn++;
	}

	struct timespec end_time;
	clock_gettime(CLOCK_REALTIME, &end_time);
	if (SortedList_length(head) != 0) exit(2);

	long long total_time = 1000000000 * (end_time.tv_sec - start_time.tv_sec) + (end_time.tv_nsec - start_time.tv_nsec);
	char* bstr = syncf();
	fprintf(stdout, "list-%s-%s,%d,%d,1,%d,%lld,%d\n", 
			yieldo, bstr, thread_count, 
			iteration_count, 3*thread_count*iteration_count, 
			total_time, (int)(total_time / (3.0*thread_count*iteration_count)));
	free(threadi);
	exit(0);
}
Пример #13
0
void* thread_func(void* argc)
{
  int i;
  //insert 
  //printf("%d\n", *(int*)argc);
  for (i = *(int*)argc; i < operations; i += num_thread) 
  {

    if (sync_s == 'm')
    {
      pthread_mutex_lock(&lock);
      SortedList_insert(&list[hash_key(element[i].key)], &element[i]);
      pthread_mutex_unlock(&lock);
    }
    else if (sync_s=='s')
    {
      while (__sync_lock_test_and_set(&locker, 1));
        SortedList_insert(&list[hash_key(element[i].key)], &element[i]);
        __sync_lock_release(&locker);
    }
    else
    {
      SortedList_insert(&list[hash_key(element[i].key)], &element[i]);
    }
  }
  int b;
  //get the length
  if (sync_s=='m')
  {
    pthread_mutex_lock(&lock);

    for (b=0; b<num_list; b++)
    {
      SortedList_length(&list[b]);
      //printf("%d\n",SortedList_length(&list[b]) );
    }
    pthread_mutex_unlock(&lock);
  }
  else if (sync_s=='s')
  {
    while (__sync_lock_test_and_set(&locker, 1));
    for (b=0; b<num_list; b++)
    {
      SortedList_length(&list[b]);
    }
    __sync_lock_release(&locker);
  }
  else
  {
    for (b=0; b<num_list; b++)
    {
      SortedList_length(&list[b]);
    }
  }

  //lookup and delete.
  SortedListElement_t* node_deleted;
  for ( i = *(int *)argc; i < operations; i += num_thread) 
    {

      if (sync_s=='m')
      {
        pthread_mutex_lock(&lock);
        node_deleted = SortedList_lookup(&list[hash_key(element[i].key)], element[i].key);
        SortedList_delete(node_deleted);
        pthread_mutex_unlock(&lock);
      } 
      else if (sync_s=='s')
      {
        while (__sync_lock_test_and_set(&locker, 1));
        node_deleted = SortedList_lookup(&list[hash_key(element[i].key)], element[i].key);
        SortedList_delete(node_deleted);
        __sync_lock_release(&locker);
      }
      else
      {
        node_deleted = SortedList_lookup(&list[hash_key(element[i].key)], element[i].key);
        
        SortedList_delete(node_deleted);
      }
    } 
}
Пример #14
0
int main(int argc, char *argv[])
{
    int i, j;
  /*
    get the options
  */

  while (1)
    {
      static struct option long_options[] =
        {
          //set value
          {"threads",  required_argument, 0, 't'},
          {"yield",  required_argument, 0, 'y'},
          {"iterations",  required_argument, 0, 'i'},
          {"sync",  required_argument, 0, 's'},
          {"lists",  required_argument, 0, 'l'},
          
          {0, 0, 0, 0}
        };
      /* getopt_long stores the option index here. */
      int option_index = 0;

      char arg = getopt_long (argc, argv, "tis",
                       long_options, &option_index);

      /* Detect the end of the options. */
      if (arg == -1)
        break;

      switch (arg)
        {
        
        case 0:
          break;


        case 't':
          num_thread = atoi(optarg);
          break;

        case 'i':
          num_iteration = atoi(optarg);
          break;

        case 's':
          sync_s = optarg[0];
          break;

        case 'l':
          num_list = atoi(optarg);
          break;

        case 'y':
          temperal = optarg;
          int i=0;
          for (i=0; temperal[i]!= '\0'; i++)
          {
            if (temperal[i]=='i')
            {
              opt_yield+=INSERT_YIELD;
            }
            else if (temperal[i]=='d')
            {
              opt_yield+=DELETE_YIELD;
            }
            else if (temperal[i]=='s')
            {
              opt_yield+=SEARCH_YIELD;
            }
            else
            {
              fprintf(stderr, "invalid option!\n");
            }

          }
          break;

        //default:
          //return 0;


        }
    }

  //initialize the list headers

  list = (SortedList_t *) malloc (num_list*sizeof(SortedList_t));

  int h;
  for (h=0; h<num_list; h++)
  {
    //list[h] = {&list[h], &list[h], NULL};
    list[h].prev = &list[h];
    list[h].next = &list[h];
    list[h].key = NULL;

  }
  
  //initialize all the node needed
  operations = num_thread * num_iteration;
  element = (SortedListElement_t *)malloc(operations*sizeof(SortedListElement_t));


  //generate key for each node
  for (i = 0; i < operations; i++)
  {
    char* temp = (char*) malloc (5*sizeof(char));
    
    temp[0]=65+rand()%60;
    temp[1]=65+rand()%60;
    temp[2]=65+rand()%60;
    temp[3]=65+rand()%60;
    temp[4]=65+rand()%60;
    element[i].key = temp;

    // element[i].key = (char*) malloc (5*sizeof(char));
    // element[i].key[0] = 65+rand()%60;
    // element[i].key[1] = 65+rand()%60;
    // element[i].key[2] = 65+rand()%60;
    // element[i].key[3] = 65+rand()%60;
    // element[i].key[4] = 65+rand()%60;



  }

  pthread_t *tids = (pthread_t *)malloc(num_thread*sizeof(pthread_t));
 


  struct timespec requestStart, requestEnd;
  clock_gettime(CLOCK_MONOTONIC, &requestStart);
    
 

  //an integer array to hold ids
  int *thread_id = (int *)malloc(num_thread*sizeof(int));
 
  for ( i = 0; i < num_thread; i++)
    thread_id[i] = i;

  int k;
  for ( k = 0; k < num_thread; k++)
    pthread_create(&tids[k], NULL, thread_func, &thread_id[k] );

  
  for ( j = 0; j < num_thread; j++)
    pthread_join(tids[j], NULL);

  clock_gettime(CLOCK_MONOTONIC, &requestEnd);
   


  int elapsed_time = diff(requestStart, requestEnd).tv_nsec;

  //print discription
  printf("%ld threads x %ld iterations x (insert + lookup/delete) = %ld operations\n",  num_thread, num_iteration, operations*2);
  printf("elapsed time: %dns\n", elapsed_time);
  printf("per operation: %ldns\n", elapsed_time/operations/2);
  int q;
  int sum_length=0;
  for (q=0; q<num_list; q++)
  {
    sum_length+=SortedList_length(&list[q]);
  }
  if (sum_length!=0)
  fprintf(stderr,"ERROR: final count = %lld\n", sum_length);

  //printf("%d\n", elapsed_time/operations/2);



  exit(0);
}