From 6cf937fb63b7f01217181c129ef561c834b4b881 Mon Sep 17 00:00:00 2001 From: Ilya Bezrukov Date: Sun, 9 Mar 2025 16:07:05 +0300 Subject: [PATCH] Add first lab work --- lab01/Makefile | 37 ++++++++++ lab01/main.c | 197 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 234 insertions(+) create mode 100644 lab01/Makefile create mode 100644 lab01/main.c diff --git a/lab01/Makefile b/lab01/Makefile new file mode 100644 index 0000000..7be4f6b --- /dev/null +++ b/lab01/Makefile @@ -0,0 +1,37 @@ +CC := gcc +CFLAGS := -Wall +BIN := bin/ +LIBS := -lpthread +SOURCES := main.c +OBJECTS = $(addprefix $(BIN), $(SOURCES:.c=.o)) +EXENAME := otp +EXENAME := $(addprefix $(BIN), $(EXENAME)) + +EXAMPLE := main.c +ENC := encrypted +DNC := decrypted + +.PHONY: all +all: $(EXENAME) + +$(EXENAME): $(OBJECTS) + $(CC) $(CFLAGS) $(OBJECTS) -o $(EXENAME) $(LIBS) + +$(BIN)%.o: %.c $(BIN) + $(CC) $(CFLAGS) -c $< -o $@ + +$(BIN): + @mkdir -p $(BIN) + +.PHONY: clean +clean: + @rm -rf $(BIN) + +.PHONY: encrypt +encrypt: $(EXENAME) + ./$(EXENAME) -i $(EXAMPLE) -o $(ENC) -x 421 -a 453 -c 4567 -m 2177823 + +.PHONY: decrypt +decrypt: + ./$(EXENAME) -i $(ENC) -o $(DNC) -x 421 -a 453 -c 4567 -m 2177823 + diff main.c decrypted diff --git a/lab01/main.c b/lab01/main.c new file mode 100644 index 0000000..e40f21f --- /dev/null +++ b/lab01/main.c @@ -0,0 +1,197 @@ +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#define eprintf(...) fprintf(stderr, __VA_ARGS__); + + +typedef struct _Config { + char ifile[PATH_MAX + 1]; + char ofile[PATH_MAX + 1]; + + size_t size; + + uint64_t x0; + uint64_t a; + uint64_t c; + uint64_t m; + + char *pad; +} Config; + + +typedef struct _Context { + pthread_t id; + pthread_barrier_t *barrier; + + size_t start; + size_t end; + size_t length; + + char *pad; + char *input; + char *output; +} Context; + + +void *lcg_gen(void *arg) { + Config *cfg = (Config*) arg; + uint64_t x = cfg->x0; + uint64_t a = cfg->a; + uint64_t c = cfg->c; + uint64_t m = cfg->m; + for (size_t i = 0; i < cfg->size; i++) { + cfg->pad[i] = x; + x = (x * a + c) % m; + } + return NULL; +} + + +void *worker(void *arg) { + Context *ctx = (Context*) arg; + printf("[worker %ld] start: %zu, end: %zu, len: %zu\n", ctx->id, ctx->start, ctx->end, ctx->length); + for (size_t i = ctx->start; i < ctx->end; i++) { + ctx->output[i] = ctx->input[i] ^ ctx->pad[i]; + } + pthread_barrier_wait(ctx->barrier); + return NULL; +} + + +int main(int argc, char *argv[]) { + Config cfg; + + char current_opt; + extern char *optarg; + extern int optind, optopt, opterr; + while ((current_opt = (char) getopt(argc, argv, "hi:o:x:a:c:m:")) != -1) { + switch (current_opt) { + case 'x': + cfg.x0 = atoi(optarg); + break; + case 'a': + cfg.a = atoi(optarg); + break; + case 'c': + cfg.c = atoi(optarg); + break; + case 'm': + cfg.m = atoi(optarg); + break; + case 'i': + strncpy(cfg.ifile, optarg, PATH_MAX); + break; + case 'o': + strncpy(cfg.ofile, optarg, PATH_MAX); + break; + case 'h': + printf("< help text here >\n"); + return EXIT_SUCCESS; + case ':': + eprintf("Option %c requires an argument!\n", optopt); + return EXIT_FAILURE; + case '?': + eprintf("Use \"%s -h\" to see help page\n", argv[0]); + return EXIT_FAILURE; + } + } + + int ifd; + int ofd; + if ((ifd = open(cfg.ifile, O_RDONLY)) == -1) { + perror("input file"); + return EXIT_FAILURE; + } + if ((ofd = open(cfg.ofile, O_WRONLY | O_CREAT, S_IREAD | S_IWRITE)) == -1) { + perror("output file"); + return EXIT_FAILURE; + } + + struct stat istat; + if (fstat(ifd, &istat) == -1) { + perror("input file"); + return EXIT_FAILURE; + } + cfg.size = (size_t) istat.st_size; + + char *input = mmap(NULL, cfg.size, PROT_READ, MAP_PRIVATE, ifd, 0); + if (input == MAP_FAILED) { + perror("input file"); + return EXIT_FAILURE; + } + char *output = calloc(sizeof(char), cfg.size); + + close(ifd); + + if ((cfg.pad = calloc(sizeof(char), cfg.size)) == NULL) { + perror("pad"); + return EXIT_FAILURE; + } + + pthread_t th_lcg_gen; + if (pthread_create(&th_lcg_gen, NULL, lcg_gen, (void*) &cfg) != 0) { + return EXIT_FAILURE; + } + pthread_join(th_lcg_gen, NULL); + + int workers_count = get_nprocs(); + Context **workers = calloc(sizeof(Context*), workers_count); + size_t blen = cfg.size / workers_count; // averrage len for one block + + printf("[main] workers count: %d\n", workers_count); + + pthread_barrier_t barrier; + if (pthread_barrier_init(&barrier, NULL, workers_count + 1) != 0) { + return EXIT_FAILURE; + } + + printf("[main] file size: %zu\n", cfg.size); + + for (int i = 0; i < workers_count; i++) { + workers[i] = calloc(sizeof(Context), 1); + workers[i]->barrier = &barrier; + workers[i]->pad = cfg.pad; + workers[i]->input = input; + workers[i]->output = output; + workers[i]->start = i * blen; + if (i == workers_count - 1) { + workers[i]->end = cfg.size; // handle remainder after integer division + } else { + workers[i]->end = (i + 1) * blen; + } + workers[i]->length = workers[i]->end - workers[i]->start; + pthread_create(&workers[i]->id, NULL, worker, (void*) workers[i]); + } + + pthread_barrier_wait(&barrier); + + for (int i = 0; i < workers_count; i++) { + pthread_join(workers[i]->id, NULL); + } + + pthread_barrier_destroy(&barrier); + munmap(input, cfg.size); + + for (int i = 0; i < workers_count; i++) { + free(workers[i]); + } + free(workers); + free(cfg.pad); + + write(ofd, output, cfg.size); + close(ofd); + free(output); + + return EXIT_SUCCESS; +}