consolidate all repos to one for archive
This commit is contained in:
12
semester_2/uvod_v_operacijske_sisteme/naloga_06/Makefile
Normal file
12
semester_2/uvod_v_operacijske_sisteme/naloga_06/Makefile
Normal 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
|
55
semester_2/uvod_v_operacijske_sisteme/naloga_06/README.md
Normal file
55
semester_2/uvod_v_operacijske_sisteme/naloga_06/README.md
Normal 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
|
33
semester_2/uvod_v_operacijske_sisteme/naloga_06/naloga_1.c
Normal file
33
semester_2/uvod_v_operacijske_sisteme/naloga_06/naloga_1.c
Normal 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;
|
||||
}
|
63
semester_2/uvod_v_operacijske_sisteme/naloga_06/naloga_2.c
Normal file
63
semester_2/uvod_v_operacijske_sisteme/naloga_06/naloga_2.c
Normal 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;
|
||||
}
|
52
semester_2/uvod_v_operacijske_sisteme/naloga_06/naloga_3.c
Normal file
52
semester_2/uvod_v_operacijske_sisteme/naloga_06/naloga_3.c
Normal 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;
|
||||
}
|
107
semester_2/uvod_v_operacijske_sisteme/naloga_06/slow.h
Normal file
107
semester_2/uvod_v_operacijske_sisteme/naloga_06/slow.h
Normal 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_
|
Reference in New Issue
Block a user