consolidate all repos to one for archive

This commit is contained in:
2025-01-28 13:46:42 +01:00
commit a6610fbc7a
5350 changed files with 2705721 additions and 0 deletions

View File

@@ -0,0 +1,12 @@
all: naloga_1 naloga_2 naloga_3
naloga_1: naloga_1.c
gcc naloga_1.c -pthread -o naloga_1
rm naloga_1.c
naloga_2: naloga_2.c
gcc naloga_2.c -pthread -o naloga_2
rm naloga_2.c
naloga_3: naloga_3.c
gcc naloga_3.c -pthread -o naloga_3
rm naloga_3.c
clean:
rm -f naloga_1 naloga_2 naloga_3

View File

@@ -0,0 +1,55 @@
Sinhronizacija niti (sprotna naloga)
V sklopu te naloge demonstrirajte uporabo konstruktov za sinhronizacijo iz knjižnice pthread. Pripravite 3 programe, ki izvedejo v nadaljevanju opisane naloge. Pripravite tudi Makefile, ki bo vašo kodo prevedel v izvedljive programe.
Za pripravo nalog je za vas pripraljena preprosta knjižnica slow.h. V njej so implementirane funkcije, ki jih morate uporabiti v rešitvah nalog 1 in 2. Knjižnico morate uporabiti kot je in jo oddati skupaj z vašimi rešitvami. Na sistemu bo zamenjana z drugo lokalno verzijo.
Posamezni naslovi podnalog v nadaljevanu so sestavljeni iz pričakovanega imena programa in pričakovanega imena izvorne zbirke. Na sistem oddajte .zip paket z Makefile skripto in izvornimi zbirkami. Bodite pozorni na poimenovanja. Pred oddajo preverite delovanje z avtomatskim preizkusom.
naloga_1 (naloga_1.c)
Program naj ustvari dve niti. Vsaka izmed teh niti naj uporabi funkcijo pisi in trikrat izpise svojo sporočilo. Prva nit naj izpisuje sporočilo "prva\n", druga pa sporočilo "druga\n".
Funkcija pisi izpisuje zelo počasi, zato bi izpis dveh različnih niti lahko bil prepleten. Da se temu izognete, morate klic funkcije izvesti kot kritičen odsek kode zaščiten z mutex-om.
naloga_2 (naloga_2.c)
Programu bosta podana dva argumenta. Prvi argument je celo število N, drugi pa celo število M.
Program naj pripravi tabelo za N celoštevilskih vrednosti in jih inicializira na 0. Pripravi in inicializira naj tudi enako veliko tabelo mutex-ov. Vsaka vrednost ima svoj mutex.
Nato naj ustvari M niti. Vsaka nit naj desetkrat ponovi naslednje operacije:
kliče funkcijo izberi_indeks s katero izbere indeks naslednjega števila
kliče funkcijo povecaj s katerim izbrani vrednosti prišteje 1 in rezultat hrani nazaj v tabelo
izpiše trenutno vrednost izbranega števila
Za opisane operacije je pomembno, da se klic funkcije izberi_indeks zgodi izven kritičnega odseka. Klic funkcije povecaj in izpis vrednosti v tabeli pa se izvede v skupnem kritičnem odseku zaščitenim z mutexom izbranega števila.
Glavna nit naj po zaključku vseh niti izpiše še končne vrednosti v tabeli.
Primeri izpisa v niti za vrednost z indeksom 3:
vrednost 3 je 4
Primer izpisa glavne niti po zaključku (za 2 niti in 5 vrednosti):
vrednosti: 6 8 4 1 1
Priložene funkcije izberi_indeks in povecaj so prilagojene tako, da vam bodo olajšale iskanje napak v sinhronizaciji. Pravilno pripravljena rešitev se bo izvedla hitro in imela pravilen izračun.
naloga_3 (naloga_3.c)
Program naj ustvari 2 niti, ki bosta izmenično 2x izpisali vsaka svoje sporočilo. Prva naj izpiše "prva\n" druga pa naj izpiše "druga\n". Za izpis uporabite mutex-e in pogojne spremenljivke.
Preko parametrov ukazne vrstice bo podana začetna nit. V kolikor je prvi argument "prva" naj z izpisom prične prva nit. V kolikor je "druga" naj prične druga nit.
Primeri uporabe:
$ ./naloga_3 prva
prva
druga
prva
druga
$ ./naloga_3 druga
druga
prva
druga
prva

View File

@@ -0,0 +1,33 @@
#include <pthread.h>
#include "slow.h"
pthread_mutex_t print_mutex = PTHREAD_MUTEX_INITIALIZER;
void* thr_main1(){
pthread_mutex_lock(&print_mutex);
pisi("prva\n");
pisi("prva\n");
pisi("prva\n");
pthread_mutex_unlock(&print_mutex);
return 0;
}
void* thr_main2(){
pthread_mutex_lock(&print_mutex);
pisi("druga\n");
pisi("druga\n");
pisi("druga\n");
pthread_mutex_unlock(&print_mutex);
return 0;
}
int main(){
pthread_t tid[2];
pthread_create(&tid[0], NULL, thr_main1, "prva");
pthread_create(&tid[1], NULL, thr_main2, "druga");
pthread_join(tid[0], NULL);
pthread_join(tid[1], NULL);
return 0;
}

View File

@@ -0,0 +1,63 @@
#include <pthread.h>
#include "slow.h"
struct ThrArg {
int max_ind;
int *tabela;
pthread_mutex_t *mutex;
} typedef ThrArgd;
ThrArgd thr_arg;
void* thr_main(){
int ret;
for(int i = 0; i < 10; i++){
ret = izberi_indeks(thr_arg.max_ind);
pthread_mutex_lock(&thr_arg.mutex[ret]);
povecaj(thr_arg.tabela, ret);
printf("vrednost %d je %d\n", ret, thr_arg.tabela[ret]);
pthread_mutex_unlock(&thr_arg.mutex[ret]);
}
return 0;
}
int main(int argc, char **argv){
int N = atoi(argv[1]);
int M = atoi(argv[2]);
pthread_mutex_t *mutex = malloc(sizeof(pthread_mutex_t)*N);
int *tabela = malloc(sizeof(int)*N);
pthread_t tid[M];
thr_arg.tabela = tabela;
thr_arg.mutex = mutex;
thr_arg.max_ind = N;
for(int i= 0; i<N; i++){
pthread_mutex_init(&mutex[i],NULL);
tabela[i] = 0;
}
for(int i=0; i<M ; i++){
pthread_create(&tid[i], NULL, thr_main, NULL);
}
for(int i = 0; i<M; i++) pthread_join(tid[i],NULL);
printf("vrednosti:");
for(int i = 0; i < N; i++) printf(" %d", tabela[i]);
printf("\n");
free(tabela);
free(mutex);
return 0;
}

View File

@@ -0,0 +1,52 @@
#include <pthread.h>
#include "slow.h"
#include <string.h>
pthread_mutex_t print_mutex = PTHREAD_MUTEX_INITIALIZER;
int oc = 2;
void* thr_main1(){
int i = 0;
while(i<2){
if(oc == 1){
printf("prva\n");
pthread_mutex_lock(&print_mutex);
oc = 2;
pthread_mutex_unlock(&print_mutex);
i++;
}
}
return 0;
}
void* thr_main2(){
int i = 0;
while( i<2){
if(oc == 2){
printf("druga\n");
pthread_mutex_lock(&print_mutex);
oc = 1;
pthread_mutex_unlock(&print_mutex);
i++;
}
}
return 0;
}
int main(int argc, char **argv){
pthread_t tid[2];
if(strcmp("prva", argv[1]) == 0){
oc = 1;
}else{
oc = 2;
}
pthread_create(&tid[0], NULL, thr_main1, NULL);
pthread_create(&tid[1], NULL, thr_main2, NULL);
pthread_join(tid[0], NULL);
pthread_join(tid[1], NULL);
return 0;
}

View File

@@ -0,0 +1,107 @@
#ifndef SLOW_H_
#define SLOW_H_
#include <stdarg.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <errno.h>
#include <pthread.h>
#include <time.h>
int printf_slow(const char* format, ...);
int pisi(const char* sporocilo){
pthread_t tid = pthread_self();
printf("pisi() klicana v niti %u\n", (int)tid);
fflush(0);
return printf_slow("%s", sporocilo);
}
static pthread_mutex_t signal_mutex = PTHREAD_MUTEX_INITIALIZER;
static pthread_cond_t signal_cond = PTHREAD_COND_INITIALIZER;
int locked = 0;
int izberi_indeks(int max_indeks){
struct timespec ts;
pthread_mutex_lock(&signal_mutex);
if(locked==0){
locked=1;
clock_gettime(CLOCK_REALTIME, &ts);
ts.tv_sec += 1;
pthread_cond_timedwait(&signal_cond, &signal_mutex, &ts);
locked=0;
}else{
pthread_cond_signal(&signal_cond);
}
pthread_mutex_unlock(&signal_mutex);
int i = random()%max_indeks;
printf("izbran indeks: %d\n", i);
return i;
}
void povecaj(int *tabela, int indeks){
int v = tabela[indeks];
usleep(1000);
pthread_t tid = pthread_self();
printf("povecaj() klicana v niti %u\n", (int)tid);
fflush(0);
tabela[indeks] = v+1;
}
int printf_slow(const char* format, ...){
// variable arguments list
va_list valist;
int ret_val;
va_start(valist, format);
// calculate length of formated string
int len = vsnprintf(NULL, 0, format, valist)+1;
va_end(valist);
// allocate space for formated string
char *str = (char*)malloc(len*sizeof(char));
// print formated string
va_start(valist, format);
ret_val = vsnprintf(str, len, format, valist);
va_end(valist);
// write string one byte at a time
// with small pauses
for(int i=0; str[i]!=0; i+=1){
write(1, &str[i], 1);
usleep(10);
}
// free the allocated space
free(str);
return ret_val;
}
int snprintf_slow(char* str, int n, const char* format, ...){
va_list valist;
char *str_base = (char*)malloc(n*sizeof(char));
memset(str_base, 0, n*sizeof(char));
int ret_val;
// print formated string
va_start(valist, format);
ret_val = vsnprintf(str_base, n, format, valist);
va_end(valist);
// copy string one byte at a time
// with small pauses
for(int i=0; i<n; i+=1){
str[i] = str_base[i];
usleep(10);
}
// free the allocated space
free(str_base);
return ret_val;
}
#endif //SLOW_H_