diff --git a/exercises/approximate-counter/Makefile b/exercises/approximate-counter/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..1982557b80603af6bd06b9bc5fe7e9925fad3235 --- /dev/null +++ b/exercises/approximate-counter/Makefile @@ -0,0 +1,19 @@ +PROG = main +OBJECTS = main.o counter.o +CC = gcc +CFLAGS = -Wall -std=c99 -pthread +CFLAGS += -I. # add the current directory to the include path + +.Phone: all +all: clean $(PROG) # build and run the program + ./$(PROG) + +$(PROG): $(OBJECTS) # link the object files into a binary + $(CC) $(CFLAGS) $^ -o $@ + +$(OBJECTS): %.o: %.c counter.h # compile the source files into object files + $(CC) $(CFLAGS) -c $< + +.PHONY: clean +clean: # remove the object files and the binary + rm -f $(OBJECTS) $(PROG) diff --git a/exercises/approximate-counter/counter.c b/exercises/approximate-counter/counter.c index 24ab997329acf6550b1599228a19382f5db7e45b..7f6d0ee770b2b97dd1cafb1ab0160bc232091825 100644 --- a/exercises/approximate-counter/counter.c +++ b/exercises/approximate-counter/counter.c @@ -1,24 +1,58 @@ #include "counter.h" void init_counter(counter_t *c, int threshold, int num_cpu) { - // TODO: Implement this function + c->num_cpu = num_cpu; + c->threshold = threshold; + c->global = 0; + c->local = malloc(num_cpu * sizeof(long)); + c->llock = malloc(num_cpu * sizeof(pthread_mutex_t)); + pthread_mutex_init(&c->glock, NULL); + int i; + for (i = 0; i < num_cpu; i++) { + c->local[i] = 0; + pthread_mutex_init(&c->llock[i], NULL); + } } -void update_counter(counter_t *c, int t_id, int amount) { - // TODO: Implement this function +void update_counter(counter_t * c, int t_id, int amount) { +int cpu = t_id % c->num_cpu; + pthread_mutex_lock(&c->llock[cpu]); + c->local[cpu] += amount; + if (c->local[cpu] >= c->threshold) { + pthread_mutex_lock(&c->glock); + c->global += c->local[cpu]; + pthread_mutex_unlock(&c->glock); + c->local[cpu] = 0; + } + pthread_mutex_unlock(&c->llock[cpu]); } int get_counter_val(counter_t *c) { - pthread_mutex_lock(&c->glock); - int val = c->global; - pthread_mutex_unlock(&c->glock); - return val; + pthread_mutex_lock(&c->glock); + int val = c->global; + pthread_mutex_unlock(&c->glock); + return val; } void sync_counter(counter_t *c) { - // TODO: Implement this function + int i; + for (i = 0; i < c->num_cpu; i++) { + pthread_mutex_lock(&c->llock[i]); + pthread_mutex_lock(&c->glock); + c->global += c->local[i]; + pthread_mutex_unlock(&c->glock); + c->local[i] = 0; + pthread_mutex_unlock(&c->llock[i]); + } + } void destroy_counter(counter_t *c) { - // TODO: Implement this function + pthread_mutex_destroy(&c->glock); + int i; + for (i = 0; i < c->num_cpu; i++) { + pthread_mutex_destroy(&c->llock[i]); + } + free(c->local); + free(c->llock); }