Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <time.h>
- #include "options.h"
- #include <threads.h>
- #define DELAY_SCALE 1000
- //Added mutex to the array struct
- struct array {
- int size;
- int *arr;
- mtx_t* mutex;
- };
- //args to create the threads
- struct args {
- int id;
- int iterations;
- int delay;
- int increase;
- struct array*array;
- };
- //Info regarding the threads
- struct thread_info {
- thrd_t id;
- struct args*args;
- };
- void apply_delay(int delay) {
- for(int i = 0; i < delay * DELAY_SCALE; i++); // waste time
- }
- int increment(int id, int iterations, int delay, struct array *arr)
- {
- int pos, val;
- for(int i = 0; i < iterations; i++) {
- pos = rand() % arr->size;
- printf("%d increasing position %d\n", id, pos);
- val = arr->arr[pos];
- apply_delay(delay);
- val ++;
- apply_delay(delay);
- arr->arr[pos] = val;
- apply_delay(delay);
- }
- return 0;
- }
- int resta_suma(void *ptr){
- struct args*args = ptr;
- int pos1, pos2, val;
- for(int i=0; i< args->iterations; i++) {
- pos1 = rand() % args->array->size;
- pos2 = rand() % args->array->size;
- printf("Thread %d decrementa la posición %d e incrementa la posición %d\n",args->id, pos1, pos2);
- if(pos1<pos2){
- mtx_lock(&args->array->mutex[pos1]);
- mtx_lock(&args->array->mutex[pos2]);
- }
- else{
- mtx_lock(&args->array->mutex[pos2]);
- mtx_lock(&args->array->mutex[pos1]);
- }
- val = args->array->arr[pos1];
- apply_delay(args->delay);
- val--;
- apply_delay(args->delay);
- args->array->arr[pos1]=val;
- val = args->array->arr[pos2];
- apply_delay(args->delay);
- val++;
- apply_delay(args->delay);
- args->array->arr[pos2]=val;
- if(pos1<pos2){
- mtx_unlock(&args->array->mutex[pos1]);
- mtx_unlock(&args->array->mutex[pos2]);
- }
- else{
- mtx_unlock(&args->array->mutex[pos2]);
- mtx_unlock(&args->array->mutex[pos1]);
- }
- }
- return 0;
- }
- //How it's supposed to work: lock the access to the array. Increment the position, add the increase to the
- // args->increase section to know how much is increased by every thread and unlock after certain delay.
- int aux_increment(void*ptr){
- struct args*args = ptr;
- int pos,val;
- for(int i =0; i < args->iterations; i++) {
- pos = rand() % args->array->size;
- printf("Thread %d increasing position %d.\n", args->id, pos);
- mtx_lock(&args->array->mutex[pos]);
- val = args->array->arr[pos];
- apply_delay(args->delay);
- val++;
- args->increase ++;
- apply_delay(args->delay);
- args->array->arr[pos] = val;
- apply_delay(args->delay);
- mtx_unlock(&args->array->mutex[pos]);
- }
- return 0;
- }
- //Print the array to check if the corresponding amounts are correct.
- void print_array(struct array*arr, struct thread_info*thred, int num_threads) {
- int total = 0;
- //Print by thread
- for(int i = 0; i < num_threads*2; i++) {
- printf("%d: %d.\n",i,thred[i].args->increase);
- }
- //Print by array
- for(int i = 0; i < arr->size; i++) {
- total += arr->arr[i];
- printf("%d ", arr->arr[i]);
- }
- printf("\nTotal: %d\n", total);
- }
- //Start threads function.
- struct thread_info* start_threads(struct options opt, struct array*array){
- int i;
- struct thread_info* threads;
- printf("Creating %d threads.\n", opt.num_threads*2);
- threads = malloc(sizeof(struct thread_info)*opt.num_threads*2);
- if(threads == NULL){
- printf("Not enough memory available.\n");
- exit(1);
- }
- for(i = 0; i < opt.num_threads; i++){
- threads[i].args = malloc(sizeof(struct args));
- threads[i].args -> id = i;
- threads[i].args -> increase = 0;
- threads[i].args -> iterations = opt.iterations;
- threads[i].args -> delay = opt.delay;
- threads[i].args -> array = array;
- if( 0!= thrd_create(&threads[i].id,aux_increment,threads[i].args));
- }
- for(i = opt.num_threads; i < opt.num_threads*2; i++){
- threads[i].args = malloc(sizeof(struct args));
- threads[i].args -> id = i;
- threads[i].args -> increase = 0;
- threads[i].args -> iterations = opt.iterations;
- threads[i].args -> delay = opt.delay;
- threads[i].args -> array = array;
- if( 0!= thrd_create(&threads[i].id,resta_suma,threads[i].args));
- }
- return threads;
- }
- //Wait function, so we can make sure every thread has finished at the end of the program.
- void wait (struct options opt, struct array*array, struct thread_info* threads){
- for(int i = 0; i < (opt.num_threads*2); i++){
- thrd_join(threads[i].id,NULL);
- }
- print_array(array,threads,opt.num_threads*2);
- for(int i = 0; i < (opt.num_threads*2); i++){
- free(threads[i].args);
- }
- free(threads);
- free(array->arr);
- }
- //Function that makes sure the mutex, array and threads are properly initialized.
- void init_arrays(struct array*array, int size){
- array->size = size;
- array->arr = malloc(array->size*sizeof(int));
- array->mutex = malloc(size* sizeof (mtx_t));
- for(int i = 0; i<array->size; i++){
- array->arr[i] = 0;
- mtx_init(&array->mutex[i],mtx_plain);
- }
- }
- //Main function.
- int main (int argc, char **argv)
- {
- struct options opt;
- struct array arr;
- struct thread_info * thred;
- srand(time(NULL));
- // Default values for the options
- opt.num_threads = 5;
- opt.size = 10;
- opt.iterations = 100;
- opt.delay = 1000;
- read_options(argc, argv, &opt);
- init_arrays(&arr,opt.size);
- thred = start_threads(opt,&arr);
- wait(opt,&arr,thred);
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement