diff --git a/Makefile b/Makefile index f4c94bb..60a39d5 100644 --- a/Makefile +++ b/Makefile @@ -7,6 +7,7 @@ OBJS = $(SRCS:.c=.o) CC = cc CFLAGS = -Wall -Wextra -Werror -pthread +# CFLAGS = -Wall -Wextra -Werror -pthread -g -fsanitize=thread all: $(NAME) @@ -24,8 +25,15 @@ $(NAME): $(OBJS) # number_of_compiles_required # dongle_cooldown # scheduler + test: $(NAME) - ./$(NAME) 10 2000 500 200 300 5 50 1 + ./$(NAME) 2 800 200 100 10 5 0 edf + +test-val: $(NAME) + valgrind --leak-check=full --show-leak-kinds=all ./$(NAME) 2 800 200 100 10 5 0 edf + +test-hel: $(NAME) + valgrind --tool=helgrind ./$(NAME) 2 800 200 100 10 5 0 edf clean: rm -f $(OBJS) diff --git a/coders/codexion.h b/coders/codexion.h index daf802e..8562803 100644 --- a/coders/codexion.h +++ b/coders/codexion.h @@ -24,17 +24,37 @@ typedef struct s_args int time_to_refactor; int number_of_compiles_required; int dongle_cooldown; - int scheduler; + char *scheduler; } t_args; -typedef struct s_data +typedef struct s_dongle +{ + pthread_mutex_t lock; + long last_used; +} t_dongle; + +typedef struct s_coder { - struct timeval start; int coder_id; + pthread_t thread; + t_dongle *right_dongle; + t_dongle *left_dongle; + long last_compile; + int compiles_done; + void *state; +} t_coder; + +typedef struct s_state +{ t_args args; - pthread_mutex_t *left_dongle; - pthread_mutex_t *right_dongle; -} t_data; + t_coder *coders; + t_dongle *dongles; + long start; + int is_over; + pthread_mutex_t over_mutex; + pthread_mutex_t print_mutex; + pthread_t monitor; +} t_state; t_args *parse_arguments(int count, char **args); diff --git a/coders/main.c b/coders/main.c index 2a0273f..a137f15 100644 --- a/coders/main.c +++ b/coders/main.c @@ -17,87 +17,140 @@ #include #include -void compile_op(t_data *data) +long now(void) { - struct timeval now; - int diff; + struct timeval current; - gettimeofday(&now, NULL); - diff = (now.tv_sec - data->start.tv_sec) * 1000L + (now.tv_usec - - data->start.tv_usec) / 1000; - printf("%d %d is compiling\n", diff, data->coder_id); - usleep(data->args.time_to_compile * 1000L); + gettimeofday(¤t, NULL); + return (current.tv_sec * 1000L + current.tv_usec / 1000); } -void debug_op(t_data *data) +void compile_op(t_coder *coder, t_state *state) { - struct timeval now; - int diff; - - gettimeofday(&now, NULL); - diff = (now.tv_sec - data->start.tv_sec) * 1000L + (now.tv_usec - - data->start.tv_usec) / 1000; - printf("%d %d is debugging\n", diff, data->coder_id); - usleep(data->args.time_to_debug * 1000L); + // acquire right dongle + pthread_mutex_lock(&coder->left_dongle->lock); + coder->left_dongle->last_used = now(); + pthread_mutex_lock(&state->print_mutex); + printf("%ld %d has taken a dongle\n", now() - state->start, + coder->coder_id); + pthread_mutex_unlock(&state->print_mutex); + // acquire right dongle + pthread_mutex_lock(&coder->right_dongle->lock); + coder->right_dongle->last_used = now(); + pthread_mutex_lock(&state->print_mutex); + printf("%ld %d has taken a dongle\n", now() - state->start, + coder->coder_id); + pthread_mutex_unlock(&state->print_mutex); + coder->last_compile = now(); + pthread_mutex_lock(&state->print_mutex); + printf("%ld %d is compiling\n", now() - state->start, coder->coder_id); + pthread_mutex_unlock(&state->print_mutex); + usleep(state->args.time_to_compile * 1000L); + pthread_mutex_unlock(&coder->left_dongle->lock); + pthread_mutex_unlock(&coder->right_dongle->lock); + coder->compiles_done += 1; } -void refactor_op(t_data *data) +void debug_op(t_coder *coder, t_state *state) { - struct timeval now; - int diff; + pthread_mutex_lock(&state->print_mutex); + printf("%ld %d is debugging\n", now() - state->start, coder->coder_id); + pthread_mutex_unlock(&state->print_mutex); + usleep(state->args.time_to_debug * 1000L); +} - gettimeofday(&now, NULL); - diff = (now.tv_sec - data->start.tv_sec) * 1000L + (now.tv_usec - - data->start.tv_usec) / 1000; - printf("%d %d is refactoring\n", diff, data->coder_id); - usleep(data->args.time_to_refactor * 1000L); +void refactor_op(t_coder *coder, t_state *state) +{ + pthread_mutex_lock(&state->print_mutex); + printf("%ld %d is refactoring\n", now() - state->start, coder->coder_id); + pthread_mutex_unlock(&state->print_mutex); + usleep(state->args.time_to_refactor * 1000L); } void *run(void *param) { + t_coder *coder; + t_state *state; int i; - t_data *data; - data = param; + coder = param; + state = (t_state *)(coder->state); i = 0; - while (i < 5) + while (i < state->args.number_of_compiles_required) { - compile_op(data); - debug_op(data); - refactor_op(data); + compile_op(coder, state); + debug_op(coder, state); + refactor_op(coder, state); i++; } return (NULL); } +void *monitor(void *param) +{ + (void)param; + return (NULL); +} + +int cleanup(t_args *args, t_coder *coders, t_dongle *dongles) +{ + if (args) + free(args); + if (coders) + free(coders); + if (dongles) + free(dongles); + return (0); +} + int main(int argc, char **argv) { - t_args *args; - pthread_t *coders; - pthread_mutex_t *dongles; - int i; - struct timeval start; - t_data *data; + int i; + t_args *args; + t_coder *coders; + t_dongle *dongles; + t_state state; args = parse_arguments(argc - 1, &argv[1]); - coders = malloc(sizeof(pthread_t) * args->number_of_coders); - dongles = malloc(sizeof(pthread_mutex_t) * args->number_of_coders); - data = malloc(sizeof(t_data) * args->number_of_coders); + if (!args) + return (cleanup(args, NULL, NULL)); + coders = malloc(sizeof(t_coder) * args->number_of_coders); + dongles = malloc(sizeof(t_dongle) * args->number_of_coders); + if (!coders || !dongles) + return (cleanup(args, coders, dongles)); + state.start = now(); + state.args = *args; + state.is_over = 0; + state.coders = coders; + state.dongles = dongles; + pthread_mutex_init(&state.print_mutex, NULL); + pthread_mutex_init(&state.over_mutex, NULL); i = 0; - gettimeofday(&start, NULL); while (i < args->number_of_coders) { - data[i].args = *args; - data[i].coder_id = i + 1; - data[i].start = start; - pthread_create(&coders[i], NULL, run, (void *)&data[i]); - pthread_mutex_init(&dongles[i], NULL); + pthread_mutex_init(&dongles[i].lock, NULL); + dongles[i].last_used = state.start - args->dongle_cooldown; i++; } i = 0; while (i < args->number_of_coders) { - pthread_join(coders[i], NULL); + coders[i].coder_id = i + 1; + coders[i].compiles_done = 0; + coders[i].last_compile = state.start; + coders[i].left_dongle = &dongles[i]; + coders[i].right_dongle = &dongles[(i + 1) % args->number_of_coders]; + coders[i].state = &state; + pthread_create(&coders[i].thread, NULL, run, &coders[i]); i++; } + pthread_create(&state.monitor, NULL, monitor, &state); + i = 0; + while (i < args->number_of_coders) + { + pthread_join(coders[i].thread, NULL); + i++; + } + pthread_join(state.monitor, NULL); + cleanup(args, coders, dongles); } diff --git a/coders/utils.c b/coders/utils.c index 4c4743d..291b463 100644 --- a/coders/utils.c +++ b/coders/utils.c @@ -12,6 +12,7 @@ #include "codexion.h" #include +#include #include #include @@ -28,22 +29,27 @@ int isnumeric(char *str) t_args *parse_arguments(int count, char **args) { - int args_int[8]; + int args_int[7]; t_args *data; int i; - if (count != 8) + if (count != 8 || !(!strcmp(args[7], "fifo") || (!strcmp(args[7], "edf")))) return (NULL); data = malloc(sizeof(t_args)); if (!data) return (NULL); - i = -1; - while (++i < 8) + i = 0; + while (i < 7) { if (!isnumeric(args[i])) return (NULL); args_int[i] = atoi(args[i]); + i++; } + if (!strcmp(args[7], "fifo")) + data->scheduler = "fifo"; + else if (!strcmp(args[7], "edf")) + data->scheduler = "edf"; data->number_of_coders = args_int[0]; data->time_to_burnout = args_int[1]; data->time_to_compile = args_int[2]; @@ -51,6 +57,5 @@ t_args *parse_arguments(int count, char **args) data->time_to_refactor = args_int[4]; data->number_of_compiles_required = args_int[5]; data->dongle_cooldown = args_int[6]; - data->scheduler = args_int[7]; return (data); }