Add first lab work
This commit is contained in:
commit
6cf937fb63
37
lab01/Makefile
Normal file
37
lab01/Makefile
Normal file
@ -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
|
||||||
197
lab01/main.c
Normal file
197
lab01/main.c
Normal file
@ -0,0 +1,197 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <pthread.h>
|
||||||
|
#include <limits.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <sys/sysinfo.h>
|
||||||
|
#include <sys/mman.h>
|
||||||
|
|
||||||
|
#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;
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user