Skip to content
Snippets Groups Projects
Commit 4bf79a5e authored by iliya's avatar iliya
Browse files

feat: ex3 done (i think?)

parent 5060be8f
No related branches found
No related tags found
No related merge requests found
*.o
Ex3_etu
#include "thread_wrapper.h"
// #include <assert.h>
#include <pthread.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define DEBUG true
#define STACK_SIZE 100000
#define THREAD_COUNT 100
#define NB_OF_PUSH_POP 1000
// Barrier used to make sure all threads are created and ready before starting
// to run the stack test
pthread_barrier_t *b;
typedef struct {
int *ptr;
int size;
int capacity;
pthread_mutex_t lock;
} stack_t;
typedef struct {
int id;
stack_t *stack;
} thr_params;
bool stack_create(stack_t *s, int max_size) {
if (max_size < 1) {
fprintf(stderr, "Stack size has to be equal to or greater than 1");
return false;
}
pthread_mutexattr_t attr;
pthread_mutexattr_init(&attr);
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK);
pthread_mutex_init(&s->lock, &attr);
// pthread_mutexattr_destroy(&attr);
s->ptr = malloc(max_size * sizeof(int));
s->capacity = max_size;
s->size = 0;
return true;
}
bool stack_is_empty(stack_t *s) { return s->size == 0; }
void stack_push(stack_t *s, int val) {
if (s->size < s->capacity) {
pthread_mutex_lock(&s->lock);
s->ptr[(s->capacity - 1) - s->size] = val;
s->size++;
pthread_mutex_unlock(&s->lock);
// fprintf(stderr, "%d has been inserted\n", val);
} else {
fprintf(stderr, "Stack is full\n");
}
}
// Returns -1 in case of an error
int stack_pop(stack_t *s) {
if (stack_is_empty(s)) {
fprintf(stderr, "Stack is empty\n");
return -1;
}
pthread_mutex_lock(&s->lock);
int ret = s->ptr[s->capacity - s->size];
s->size--;
pthread_mutex_unlock(&s->lock);
return ret;
}
void stack_destroy(stack_t *s) {
if (s->ptr != NULL) {
pthread_mutex_destroy(&s->lock);
free(s->ptr);
}
}
void *test_stack(void *data) {
bar_wait(b);
thr_params *p = (thr_params *)data;
struct timespec ts;
clock_gettime(CLOCK_MONOTONIC, &ts);
unsigned int seed = (unsigned int)ts.tv_nsec;
for (int i = 0; i < NB_OF_PUSH_POP; i++) {
// push
int val = rand_r(&seed) % 1000;
stack_push(p->stack, val);
// pop
if (!stack_is_empty(p->stack)) {
stack_pop(p->stack);
}
}
return NULL;
}
// Testing if stack is correctly implemented in a single-threaded setting
// int main(void) {
// stack_t s;
//
// if (!stack_create(&s, 10)) {
// exit(EXIT_FAILURE);
// }
//
// for (int i = 0; i < 10; i++) {
// stack_push(&s, i);
// }
//
// for (int i = 0; i < 20; i++) {
// fprintf(stdout, "stack_pop returned: %d\n", stack_pop(&s));
// }
//
// stack_destroy(&s);
//
// return EXIT_SUCCESS;
// }
int main() {
b = bar_create(THREAD_COUNT);
stack_t s;
if (!stack_create(&s, STACK_SIZE)) {
fprintf(stderr, "Failed creating stack!\n");
return EXIT_FAILURE;
}
#ifdef DEBUG
printf("Created stack of %d\n", STACK_SIZE);
#endif
#ifdef DEBUG
printf("Launching %d threads\n", THREAD_COUNT);
#endif
pthread_t t[THREAD_COUNT];
thr_params p[THREAD_COUNT];
for (int i = 0; i < THREAD_COUNT; i++) {
p[i].id = i;
p[i].stack = &s;
thread_create(&t[i], test_stack, &p[i]);
}
for (int i = 0; i < THREAD_COUNT; i++)
thread_join(t[i], NULL);
#ifdef DEBUG
printf("Stack empty ? %s\n", stack_is_empty(&s) ? "yes" : "NO!");
#endif
stack_destroy(&s);
#ifdef DEBUG
printf("Stack destroyed\n");
#endif
bar_destroy(b);
return EXIT_SUCCESS;
}
CC=gcc -Wall -Wextra -std=gnu99 -g
LIBS=-lpthread -lm -lrt
SRCS=$(wildcard *.c)
OBJS=$(SRCS:.c=.o)
BINS=$(SRCS:%.c=%)
all: Ex3_etu
Ex3_etu: Ex3_etu.o thread_wrapper.o
$(CC) $^ -o $@ $(LIBS)
Ex3_etu.o: Ex3_etu.c thread_wrapper.h
$(CC) $< -c
thread_wrapper.o: thread_wrapper.c thread_wrapper.h
$(CC) $< -c
clean:
rm -f $(BINS) $(OBJS)
#include <error.h>
#include <errno.h>
#include <stdlib.h>
#include "thread_wrapper.h"
#define ERR_CODE 1
pthread_mutex_t *mutex_create() {
pthread_mutex_t *mutex = malloc(sizeof(pthread_mutex_t));
if (!mutex) error(ERR_CODE, ENOMEM, "malloc failed!");
pthread_mutexattr_t attr;
pthread_mutexattr_init(&attr);
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK);
int status = pthread_mutex_init(mutex, &attr);
if (status) error(ERR_CODE, status, "pthread_mutex_init failed!");
pthread_mutexattr_destroy(&attr);
return mutex;
}
void mutex_lock(pthread_mutex_t *mutex) {
int status = pthread_mutex_lock(mutex);
if (status) error(ERR_CODE, status, "pthread_mutex_lock failed!");
}
void mutex_unlock(pthread_mutex_t *mutex) {
int status = pthread_mutex_unlock(mutex);
if (status) error(ERR_CODE, status, "pthread_mutex_unlock failed!");
}
void mutex_destroy(pthread_mutex_t *mutex) {
int status = pthread_mutex_destroy(mutex);
if (status) error(ERR_CODE, status, "pthread_mutex_destroy failed!");
free(mutex);
}
pthread_barrier_t *bar_create(int count) {
pthread_barrier_t *b = malloc(sizeof(pthread_barrier_t));
int status = pthread_barrier_init(b, NULL, count);
if (status) error(ERR_CODE, status, "pthread_barrier_init failed!");
return b;
}
void bar_destroy(pthread_barrier_t *b) {
int status = pthread_barrier_destroy(b);
if (status) error(ERR_CODE, status, "pthread_barrier_destroy failed!");
free(b);
}
void bar_wait(pthread_barrier_t *b) {
int status = pthread_barrier_wait(b);
if (status != PTHREAD_BARRIER_SERIAL_THREAD && status != 0) error(ERR_CODE, status, "pthread_barrier_wait failed!");
}
void thread_create(pthread_t *thread, void *(*start_routine)(void *), void *arg) {
int status = pthread_create(thread, NULL, start_routine, arg);
if (status) error(ERR_CODE, status, "pthread_create failed!");
}
void thread_join(pthread_t thread, void **retval) {
int status = pthread_join(thread, retval);
if (status) error(ERR_CODE, status, "pthread_join failed!");
}
#ifndef _THREAD_WRAPPER_H_
#define _THREAD_WRAPPER_H_
#include <pthread.h>
extern pthread_mutex_t *mutex_create();
extern void mutex_lock(pthread_mutex_t *mutex);
extern void mutex_unlock(pthread_mutex_t *mutex);
extern void mutex_destroy(pthread_mutex_t *mutex);
extern pthread_barrier_t *bar_create(int count);
extern void bar_destroy(pthread_barrier_t *b);
extern void bar_wait(pthread_barrier_t *b);
extern void thread_create(pthread_t *thread, void *(*start_routine)(void *), void *arg);
extern void thread_join(pthread_t thread, void **retval);
#endif
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment