├── 01introC ├── Lezione3.pdf ├── Lezione4.pdf ├── Lezione4contipi.pdf ├── letturaStringhe.pdf ├── makefile ├── sommaprod.c ├── charstr.c ├── creafiles.c ├── astringhe.c ├── parametri.c ├── somma.c ├── argv.c ├── scanf.c ├── sommad.c ├── leggi_interi.c ├── stringhe.c ├── scrivi_primi.c └── primi.c ├── 08condVar ├── CondVar.pdf ├── Readme.md ├── semC11.h ├── zem.c ├── makefile ├── heap.c ├── xerrori.h └── rw.c ├── 10segnali ├── Safety.pdf ├── makefile ├── segnali.c ├── Readme.md ├── segnali_wait.c ├── xerrori.h └── segnaliRT.c ├── 07threads ├── semafori.pdf ├── numeri.py ├── makefile ├── contaprimi.c ├── atcontaprimi.c ├── xerrori.h ├── tabella_primi.c └── quicksort.c ├── 04fileBinari ├── systemCalls.pdf ├── makefile ├── Readme.md ├── write_speed.c ├── leggi_bin.c ├── scrivi_primi_bin.c ├── scrivi_primi_sc.c └── matrice.c ├── 02struct ├── persone.txt ├── capitali.txt ├── sudAmerica.txt ├── makefile ├── funzfunz.c ├── statiche.c ├── parole.c ├── qsortstr.c ├── strint.h ├── leggicitta.c ├── legginomi.c ├── bitops.c ├── qsortint.c ├── array_file.c └── frequenze.c ├── README.md ├── 05java ├── Cammino.java ├── Nodo.java ├── italiane.txt ├── Arco.java ├── Readme.md ├── coppia.java ├── LogGrafo.java ├── GrafoCitta.java ├── Grafo.java └── Citta.java ├── 09processi ├── Readme.md ├── lettore.c ├── lettore.py ├── moria.c ├── shm0.c ├── makefile ├── scrittore.c ├── shm_cons.c ├── shm_prod.c ├── contaprimi.c └── xerrori.h ├── 03assembler ├── filetypes.asm ├── makefile ├── strcmp.s ├── strcmp.c ├── primo.s ├── array_primi.s ├── primi.c ├── Readme.md ├── array_primi.c └── bespin2.conf ├── 11pythreads ├── threads.py ├── esempiPool.py ├── sommaprimi.py ├── rw.py └── somma_primi_files.py ├── 12atomic ├── makefile └── spinlock.c └── 06python ├── argomenti.py ├── PyvsC.py └── serieA.py /01introC/Lezione3.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Laboratorio2B/2425-Lab2B/HEAD/01introC/Lezione3.pdf -------------------------------------------------------------------------------- /01introC/Lezione4.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Laboratorio2B/2425-Lab2B/HEAD/01introC/Lezione4.pdf -------------------------------------------------------------------------------- /08condVar/CondVar.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Laboratorio2B/2425-Lab2B/HEAD/08condVar/CondVar.pdf -------------------------------------------------------------------------------- /10segnali/Safety.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Laboratorio2B/2425-Lab2B/HEAD/10segnali/Safety.pdf -------------------------------------------------------------------------------- /07threads/semafori.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Laboratorio2B/2425-Lab2B/HEAD/07threads/semafori.pdf -------------------------------------------------------------------------------- /01introC/Lezione4contipi.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Laboratorio2B/2425-Lab2B/HEAD/01introC/Lezione4contipi.pdf -------------------------------------------------------------------------------- /01introC/letturaStringhe.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Laboratorio2B/2425-Lab2B/HEAD/01introC/letturaStringhe.pdf -------------------------------------------------------------------------------- /04fileBinari/systemCalls.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Laboratorio2B/2425-Lab2B/HEAD/04fileBinari/systemCalls.pdf -------------------------------------------------------------------------------- /01introC/makefile: -------------------------------------------------------------------------------- 1 | # il funzionamento del makefile lo vedremo prossimamente 2 | 3 | # definizione del compilatore e dei flag di compilazione 4 | # che vengono usati dalle regole implicite 5 | CC=gcc 6 | CFLAGS=-std=c11 -Wall -O -g 7 | LDLIBS=-lm 8 | 9 | 10 | -------------------------------------------------------------------------------- /02struct/persone.txt: -------------------------------------------------------------------------------- 1 | Bruce Wayne; James Gordon 2 | Denethor; Boromir;; ;;; Faramir 3 | 4 | Coriolanus Snow; Cinna; Caesar Flickerman; 5 | Marty McFly; Emmett Brown 6 | Oliver Queen; 7 | Barry Allen; Iris West; Caitlin Snow; Francisco Ramon 8 | Morpheus; Trinity; ;Neo; Niobe; 9 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## Materiale didattico per il corso di Laboratorio 2B, Anno accademico 2024/25 2 | 3 | Questo repository contiene gli esempi di codice fatti a lezione e il registro delle lezioni. Altro materiale utile si trova sul [corso Moodle](https://elearning.di.unipi.it/course/view.php?id=1013). 4 | -------------------------------------------------------------------------------- /05java/Cammino.java: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | Classe per memorizzare un cammino di costo minimo 4 | da un nodo al nodo sorgente. 5 | per mantenere la rappresentazione compatta, 6 | memorizzo il nodo precedente e il costo del cammino */ 7 | public class Cammino { 8 | Nodo precedente = null; 9 | double costo = Double.NaN; 10 | 11 | public Cammino(Nodo p, double c) { 12 | precedente = p; 13 | costo = c; 14 | } 15 | 16 | public String toString() { 17 | return String.format("%5.2f --> %-12s", costo, precedente.etichetta()); 18 | } 19 | } -------------------------------------------------------------------------------- /04fileBinari/makefile: -------------------------------------------------------------------------------- 1 | # Per maggiori informazioni sul comando make: 2 | # http://www.cs.colby.edu/maxwell/courses/tutorials/maketutor/ 3 | # Sulle variabili automatiche vedere: 4 | # https://www.gnu.org/software/make/manual/html_node/Automatic-Variables.html 5 | 6 | # definizione del compilatore e dei flag di compilazione 7 | # che vengono usati dalle regole implicite 8 | CC=gcc 9 | CFLAGS=-std=c11 -Wall -O -g 10 | LDLIBS=-lm 11 | 12 | EXECS=scrivi_primi_bin 13 | 14 | all: $(EXECS) 15 | 16 | clean: 17 | rm -f $(EXECS) *.o 18 | 19 | 20 | -------------------------------------------------------------------------------- /05java/Nodo.java: -------------------------------------------------------------------------------- 1 | 2 | 3 | /** 4 | * Interfaccia per rappresentare un nodo di un grafo 5 | * l'unica richiesta per il tipo nodo (attualmente) 6 | * è che ogni nodo abbia un'etichetta che viene 7 | * usata per identificarlo in modo univoco 8 | * 9 | * Qualsiasi classe che ha il metodo etichetta() può essere un nodo 10 | * di un grafo, semplicemente implementando questa interfaccia 11 | */ 12 | 13 | public interface Nodo { 14 | 15 | /** restituisce l'etichetta del nodo 16 | nodi diversi devono avere etichette diverse */ 17 | public String etichetta(); 18 | 19 | } -------------------------------------------------------------------------------- /09processi/Readme.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ## Esercizi 4 | 5 | 6 | 7 | ### Processi consumatori multipli (25/3/25) 8 | 9 | Modificare l'esempio `shm_prod.c/shm_cons.c` in modo che 1) vengano utilizzati 3 consumatori e 2) i consumatori (eseguibile `shm_cons.out`) vengono lanciati dal produttore `shm_prod.out` utilizzado `fork` e `exec`. 10 | 11 | Si osservi che i consumatori necessitano di una variabile `cindex` condivisa e di un relativo mutex per regolarne l'accesso; a questo scopo conviene che il produttore crei un nuovo blocco di memoria condivisa con un unico intero e un ulteriore semaforo con nome da utilizzare come mutex (in alternativa a creare un nuovo blocco il blocco usato per il buffer può essere creato di dimensione `Buf_size+1`). 12 | 13 | 14 | -------------------------------------------------------------------------------- /09processi/lettore.c: -------------------------------------------------------------------------------- 1 | // programma per la lettura di interi da una named pipe 2 | 3 | #include "xerrori.h" 4 | 5 | #define QUI __LINE__,__FILE__ 6 | 7 | 8 | int main(int argc, char *argv[]) 9 | { 10 | if(argc!=2) { 11 | printf("Uso:\n\t%s nome_pipe\n",argv[0]); 12 | exit(1); 13 | } 14 | // apre file descriptor associato alla named pipe 15 | // se il file non esiste termina con errore 16 | int fd = open(argv[1],O_RDONLY); 17 | if(fd<0) termina("Errore apertura named pipe"); 18 | puts("lettore.out inizia la lettura"); 19 | while(true) { 20 | int val; 21 | ssize_t e = read(fd,&val,sizeof(val)); 22 | if(e==0) break; 23 | if(val%10000==0) 24 | printf("Letto: %d\n",val); 25 | } 26 | xclose(fd,QUI); 27 | printf("Lettura finita\n"); 28 | return 0; 29 | } 30 | -------------------------------------------------------------------------------- /02struct/capitali.txt: -------------------------------------------------------------------------------- 1 | Varsavia 52.2296756 21.0122287 2 | Berlino 52.4938053 13.4552919 3 | Londra 51.5073509 -0.1277583 4 | Roma 41.9027834 12.4963655 5 | Madrid 40.4167754 -3.7037902 6 | Parigi 48.856614 2.3522219 7 | Vienna 48.2081743 16.3738189 8 | Budapest 47.497912 19.040235 9 | Bucarest 44.4267674 26.1025384 10 | Chisinau 47.0104529 28.8638101 11 | Tirana 41.3275459 19.8186982 12 | Zagabria 45.8150108 15.9819189 13 | Sarajevo 43.8562586 18.4130763 14 | Lubiana 46.0569465 14.5057515 15 | Skopje 41.9973462 21.4279956 16 | Podgorica 42.4304196 19.2593642 17 | Sofia 42.6977081 23.3218675 18 | Atene 37.9838096 23.7275388 19 | Istanbul 41.0082376 28.9783589 20 | Lisbona 38.7222524 -9.1393366 21 | Praga 50.0755381 14.4378005 22 | Bratislava 48.1485965 17.1077478 23 | Belgrado 44.8307447 20.4514271 24 | Berna 46.947149 7.4515161 25 | Bruxelles 50.848402 4.3524724 26 | -------------------------------------------------------------------------------- /02struct/sudAmerica.txt: -------------------------------------------------------------------------------- 1 | São Paulo; 21486; Brasile 2 | Buenos Aires; 15748; Argentina 3 | Rio de Janeiro; 12306 ; Brasile 4 | Lima; 10556 ; Perú; 5 | Bogotá; 10252 ; Colombia 6 | Santiago; 7099 ; Cile 7 | Belo Horizonte; 5242 ; Brasile 8 | Recife; 3866; Brasile 9 | Porto Alegre; 3504; Brasile 10 | Fortaleza; 3415; Brasile 11 | Brasilia; 3406; Brasile 12 | Salvador; 3344; Brasile 13 | Medellín; 3242; Colombia 14 | Guayaquil; 3183; Ecuador 15 | Curitiba; 2873; Brasile 16 | Campinas; 2789; Brasile 17 | Quito; 2778; Ecuador 18 | Goiânia; 2663; Brasile 19 | Cali; 2640; Colombia 20 | Caracas; 2521; Venezuela 21 | Manaus; 2327; Brasile 22 | Santa Cruz de la Sierra; 2230; Bolivia 23 | Maracaibo; 2219; Venezuela 24 | Barranquilla; 2133; Colombia 25 | Belém; 2130; Brasile 26 | La Paz; 2069; Bolivia 27 | Vitória; 1731; Brasile 28 | Asunción; 1609; Paraguay 29 | Cordoba; 1597; Argentina -------------------------------------------------------------------------------- /09processi/lettore.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # legge interi dalla pipe passata sulla linea di comando 3 | # equivalente al programma C lettore.c 4 | 5 | import sys, os, struct 6 | 7 | 8 | def main(nome): 9 | fd = os.open(nome,os.O_RDONLY) 10 | print(f"=={os.getpid()}== {nome} aperto in lettura",file=sys.stderr) 11 | tot = 0 12 | while True: 13 | # legge fino a 4 byte mettendoli in un bytarray 14 | bs = os.read(fd,4) 15 | if len(bs)==0: # non c'e' nessuno che scrive: termina 16 | break 17 | tot +=1 18 | # converte i 4 byte letti in un intero e lo stampa 19 | valore = struct.unpack(" // permette di usare scanf printf etc ... 3 | #include // conversioni stringa/numero exit() etc ... 4 | #include // gestisce tipo bool (per variabili booleane) 5 | #include // permette di usare la funzione assert 6 | #include // funzioni di confronto/copia/etc di stringhe 7 | 8 | 9 | // esempio di funzione che restituisce 2 valori 10 | // scrive il prodotto a*b nella variabile 11 | // a cui punta p e restituisce la somma a+b 12 | int sommaprod(int a, int b, int *p) 13 | { 14 | *p = a*b; 15 | return a+b; 16 | } 17 | 18 | 19 | int main(int argc, char *argv[]) 20 | { 21 | // calcolo di somma e prodotto di 6 e 11 22 | int n=6; 23 | int m=11; 24 | int somma, prodotto; 25 | // per ottenere il prodotto passo il suo indirizzo 26 | somma = sommaprod(n,m,&prodotto); 27 | printf("Somma: %d, prodotto: %d\n",somma,prodotto); 28 | return 0; 29 | } 30 | -------------------------------------------------------------------------------- /03assembler/strcmp.s: -------------------------------------------------------------------------------- 1 | @; input: 2 | @; r0, r1: array caratteri 0-terminati 3 | @; output: 4 | @; r0: valore < > ==0 a seconda che la stringa r0 sia 5 | @; lessicograficamente minore maggiore o uguale a r1 6 | 7 | .data 8 | 9 | .text 10 | .global armcmp @; nome funzione chiamabile dall'esterno 11 | .type armcmp, %function @; dice all'assembler che armcmp è una funzione 12 | 13 | armcmp: 14 | cmp r0,#0 15 | moveq r0,#11 16 | beq exit @; r0==NULL exit(11) 17 | cmp r1,#0 18 | moveq r0,#12 19 | beq exit @; r1==NULL exit(12) 20 | mov r2,#0 @; for(i=0 ....) 21 | fori: 22 | ldrb r3,[r0,r2] @; r3 = r0[r2] 23 | ldrb r12,[r1,r2] @; r12 = r1[r2] 24 | cmp r3,r12 25 | subne r0,r3,r12 26 | movne pc,lr @; return r3-12=r0[r2]-r1[r2] 27 | cmp r3,#0 28 | moveq r0,#0 29 | moveq pc,lr @; return 0 30 | add r2,r2,#1 @; r2++ 31 | b fori 32 | 33 | 34 | @; necessario per arm-linux-gnueabihf-gcc per evitare il warning 35 | @; missing .note.GNU-stack section implies executable stack 36 | .section .note.GNU-stack,"",%progbits 37 | -------------------------------------------------------------------------------- /11pythreads/threads.py: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env python3 2 | 3 | import sys, threading, time 4 | 5 | 6 | # funzione eseguita dai singoli thread 7 | def countdown(a,pausa): 8 | for i in range (a,-1,-1): 9 | print(f"{threading.current_thread().name}" ,"-->", i) 10 | time.sleep(0.5) # attende pausa secondi 11 | 12 | 13 | def main(lista): 14 | # thread creati 15 | th = [] 16 | # crea e avvia un thread per ogni elemento in lista 17 | for s in lista: 18 | # passo in target la funzione da eseguire 19 | # e in args gli argomenti della funzione (in una tupla) 20 | x = threading.Thread(target=countdown, args=(int(s),0.5)) 21 | x.start() 22 | th.append(x) # salva il thread nella lista 23 | # attende terminazione dei thread 24 | for y in th: 25 | y.join() 26 | print(f"Thread {y.name} terminato") 27 | return 28 | 29 | 30 | # invoca il main con i parametri passati sulla linea di comando 31 | if len(sys.argv)>1: 32 | main(sys.argv[1:]) 33 | else: 34 | print("Uso:\n\t %s i1 [i2 i3 ...]" % sys.argv[0]) 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /04fileBinari/Readme.md: -------------------------------------------------------------------------------- 1 | ## Esercizi 2 | 3 | 4 | ### Triangolo di Tartaglia (22/10/24) 5 | 6 | Il [triangolo di Tartaglia](https://it.wikipedia.org/wiki/Triangolo_di_Tartaglia) contiene i coefficienti binomali: 7 | ``` 8 | 1 9 | 1 1 10 | 1 2 1 11 | 1 3 3 1 12 | 1 4 6 4 1 13 | ... 14 | ``` 15 | 16 | Per i=0,1,2,... la riga i-esima contiene i+1 valori 17 | ``` 18 | t[i][0] ... t[i][i] 19 | ``` 20 | che soddisfano alla relazione `t[i][0] = t[i][i] = 1` e per *k=1,...,i-1* 21 | ``` 22 | t[i][k] = t[i-1][k-1] + t[i-1][k] 23 | ``` 24 | 25 | Scrivere una procedura `int **tartaglia(int n)` che dato un intero *n* restituisce le prime *n* righe del triangolo di tartaglia. Si noti che il triangolo può essere visto come una matrice in cui la prima riga ha 1 elemento, la seconda due, etc. 26 | 27 | Scrivere poi un *main* che legge un intero positivo *n* dalla riga di comando invoca la procedura `tartaglia` passando *n* come argomento, stampa il triangolo risultante e dealloca tutta la memoria utilizzata. 28 | 29 | Verificare con valgrind che il programma acceda solo a memoria precedentemente allocata e che al termine del'esecuzione tutta la memoria venga rilasciata. 30 | 31 | 32 | -------------------------------------------------------------------------------- /02struct/funzfunz.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | // prototipo di applica: il terzo argomento ha come tipo: 7 | // puntatore a funzione che prende come input due interi e 8 | // restituisce un intero 9 | int applica(int x, int y, int (*f)(int, int)); 10 | 11 | 12 | // funzioni somma e prodotto che prendono come 13 | // input due interi e restituiscono un intero 14 | int somma(int a, int b) 15 | { 16 | return a+b; 17 | } 18 | 19 | int prod(int a, int b) 20 | { 21 | return a*b; 22 | } 23 | 24 | int neg(int a) 25 | { 26 | return -a; 27 | } 28 | 29 | 30 | 31 | int main(int argc, char *argv[]) 32 | { 33 | int a,b; 34 | 35 | if (argc!=3) { 36 | fprintf(stderr,"Uso:\n\t%s a b\n",argv[0]); exit(1); 37 | } 38 | a = atoi(argv[1]); 39 | b = atoi(argv[2]); 40 | printf("Somma: %d, Prodotto %d\n", 41 | applica(a,b,&somma), 42 | applica(a,b,&neg)); 43 | return 0; 44 | } 45 | 46 | // funzione che prende in input due interi e una funzione 47 | // e applica la funzione ai due interi 48 | int applica(int x, int y, int (*f)(int, int)) { 49 | int z = f(x,y); 50 | return z; 51 | } 52 | 53 | 54 | -------------------------------------------------------------------------------- /08condVar/Readme.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ## Esercizi 4 | 5 | 6 | 7 | ### Soluzione fair per RW (20/3/25) 8 | 9 | Modificare il file `rw.c` per implementare la soluzione fair per il problema lettori/scrittori che avete visto a AESOP (quella con il mutex `ordering` oltre alla condition variable e il mutex associato). Nell'esempio contenuto nel main dovrebbe l'accesso dovrebbe risultare effettivamente fair, nel senso che nessun thread "sorpassa" un altro nell'accesso alla strattura dati. Riporto qui sotto l'output che ottenuto io con questa variante (come a lezione ogni thread è identificato dalle ultime due cifre del tid): 10 | ```bash 11 | 40 read request 12 | 41 read request 13 | 42 write request 14 | 43 read request 15 | 44 read request 16 | 45 read request 17 | 46 read request 18 | 47 read request 19 | 48 read request 20 | 49 write request 21 | 50 read request 22 | 51 read request 23 | 52 read request 24 | 53 read request 25 | 40 read completed 26 | 41 read completed 27 | 42 write completed 28 | 43 read completed 29 | 44 read completed 30 | 45 read completed 31 | 46 read completed 32 | 47 read completed 33 | 48 read completed 34 | 49 write completed 35 | 50 read completed 36 | 51 read completed 37 | 52 read completed 38 | 53 read completed 39 | ``` 40 | 41 | -------------------------------------------------------------------------------- /02struct/statiche.c: -------------------------------------------------------------------------------- 1 | /* ********************************************************* 2 | * Esempio uso varabili statiche 3 | * ********************************************************* */ 4 | #include // permette di usare scanf printf etc ... 5 | #include // conversioni stringa/numero rand() abs() exit() etc ... 6 | #include // gestisce tipo bool (per variabili booleane) 7 | #include // permette di usare la funzione assert 8 | #include // prototipi delle funzioni per la manipolazione delle stringhe 9 | 10 | // Scopo del programma: 11 | // mostrare come le variabili statiche mantengano 12 | // il loro valore da una esecuzione all'altra della funzione 13 | 14 | 15 | // esempio di funzione con variabile statica 16 | int funz(int x) 17 | { 18 | static int y=3; // questa inizializzazione avviene solo alla prima esecuzione 19 | int z = x+y; 20 | y += 1; // il valore di y viene incrementato ad ogni esecuzione 21 | if(x==0) y=3; // ma se x==0 y viene riportato a 3 22 | return z; 23 | } 24 | 25 | // invoca funz() per ogni intero passato sulla linea di comando 26 | int main(int argc, char *argv[]) 27 | { 28 | for(int i=1;i0, "L'input deve essere positivo" 13 | if n==1: 14 | return False 15 | if n==2: 16 | return True 17 | if n%2 == 0: 18 | return False 19 | assert n>=3 and n%2==1, "C'e' qualcosa che non funziona" 20 | for i in range(3,n//2,2): 21 | if n%i==0: 22 | return False 23 | if i*i > n: 24 | break 25 | return True 26 | 27 | 28 | def main(n,cifre): 29 | tot_primi = somma_primi = 0 30 | for i in range(n): 31 | x = random.randint(0, 10**(cifre)) 32 | if x%2==0: 33 | x += 1 34 | while x%3==0 or x%5 ==0 or x%7==0: 35 | x += 2 36 | if primo(x): 37 | tot_primi += 1 38 | somma_primi += x 39 | print(x) 40 | print("Trovati",tot_primi,"primi",file=sys.stderr) 41 | print("La cui somma è",somma_primi,file=sys.stderr) 42 | 43 | if len(sys.argv)!=3: 44 | print("Uso:\n\t %s numero_interi cifre" % sys.argv[0]) 45 | else: 46 | main(int(sys.argv[1]), int(sys.argv[2]) ) 47 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /09processi/shm0.c: -------------------------------------------------------------------------------- 1 | #include "xerrori.h" 2 | 3 | // esempio semplice creazione di un array in memoria condivisa 4 | // l'array viene semplicemente scritto, lo ritrovo in /dev/shm 5 | // a meno che non prenoti la cancellazione con sem_unlink 6 | 7 | #define QUI __LINE__,__FILE__ 8 | 9 | 10 | int main(int argc,char *argv[]) 11 | { 12 | if(argc!=3) { 13 | fprintf(stderr,"Uso\n\t%s nome_shared_mem dim_array\n", argv[0]); 14 | exit(1); 15 | } 16 | // conversione input per ottenere dimensione array 17 | int n= atoi(argv[2]); 18 | if(n<1) termina("limite non valido"); 19 | 20 | // ---- creazione array memoria condivisa 21 | int shm_size = n*sizeof(int); // numero byte nella memoria condivisa 22 | int fd = xshm_open(argv[1],O_RDWR|O_CREAT, 0666,QUI); 23 | xftruncate(fd, shm_size, QUI); 24 | int *a = simple_mmap(shm_size,fd, QUI); 25 | close(fd); // dopo mmap e' possibile chiudere il file descriptor 26 | // scommentare per prenotare la cancellazione dell'oggetto nella shared memory 27 | // xshm_unlink(argv[1],QUI); // distrugge shm quando finito 28 | 29 | // riempio array 30 | for(int i=0; i 3 | 4 | // Semaphore structure 5 | typedef struct { 6 | int value; // Semaphore value 7 | mtx_t mutex; // Mutex to protect the semaphore 8 | cnd_t cond; // Condition variable for signaling 9 | } sem11_t; 10 | 11 | // Initialize the semaphore 12 | int sem11_init(sem11_t *sem, int value) { 13 | if (value < 0) { 14 | return -1; // Semaphore value must be non-negative 15 | } 16 | sem->value = value; 17 | if (mtx_init(&sem->mutex, mtx_plain) != thrd_success) { 18 | return -1; 19 | } 20 | if (cnd_init(&sem->cond) != thrd_success) { 21 | mtx_destroy(&sem->mutex); 22 | return -1; 23 | } 24 | return 0; 25 | } 26 | 27 | // Wait (decrement) the semaphore 28 | int sem11_wait(sem11_t *sem) { 29 | mtx_lock(&sem->mutex); 30 | while (sem->value <= 0) { 31 | cnd_wait(&sem->cond, &sem->mutex); // Wait until the semaphore value is positive 32 | } 33 | sem->value--; // Decrement the semaphore value 34 | mtx_unlock(&sem->mutex); 35 | return 0; 36 | } 37 | 38 | // Post (increment) the semaphore 39 | int sem11_post(sem11_t *sem) { 40 | mtx_lock(&sem->mutex); 41 | sem->value++; // Increment the semaphore value 42 | cnd_signal(&sem->cond); // Signal one waiting thread 43 | mtx_unlock(&sem->mutex); 44 | return 0; 45 | } 46 | 47 | // Destroy the semaphore 48 | int sem11_destroy(sem11_t *sem) { 49 | mtx_destroy(&sem->mutex); 50 | cnd_destroy(&sem->cond); 51 | return 0; 52 | } 53 | 54 | -------------------------------------------------------------------------------- /09processi/scrittore.c: -------------------------------------------------------------------------------- 1 | #include "xerrori.h" 2 | 3 | #define QUI __LINE__,__FILE__ 4 | 5 | // definire questa costante per far eseguire 6 | // il lettore con execl() 7 | #define USA_EXEC 8 | 9 | int main(int argc, char *argv[]) 10 | { 11 | if(argc!=2) { 12 | printf("Uso:\n\t%s nome_pipe\n",argv[0]); 13 | exit(1); 14 | } 15 | 16 | // crea la named pipe da usare per le comunicazioni 17 | int e = mkfifo(argv[1],0660); 18 | if(e==0) 19 | puts("Named pipe creata"); 20 | else if(errno== EEXIST) 21 | puts("La named pipe esiste già; procedo..."); 22 | else 23 | xtermina("Errore creazione named pipe",QUI); 24 | 25 | 26 | #ifdef USA_EXEC 27 | // faccio partire il lettore, eventualmente anche un programma python 28 | if(xfork(QUI)==0) { 29 | if(execl("lettore.py", "lettore.???", argv[1], (char *) NULL)==-1) 30 | xtermina("execl fallita",QUI); 31 | } 32 | #endif 33 | 34 | // apre file descriptor associato alla named pipe 35 | int fd = open(argv[1], O_WRONLY); 36 | if (fd < 0) // se il file non esiste termina con errore 37 | xtermina("Errore apertura named pipe", QUI); 38 | // scrive interi sulla pipe per sempre 39 | puts("Ora inizio a scrivere"); 40 | for (int val = 0; ; val++) { 41 | ssize_t e = write(fd,&val,sizeof(val)); 42 | if(e!=sizeof(val)) 43 | xtermina("Errore scrittura pipe",QUI); 44 | if(val%10000==0) 45 | fprintf(stderr,"%d: scritti %d interi\n",getpid(),val); 46 | } 47 | xclose(fd,QUI); 48 | printf("Io %d ho finito.\n",getpid()); 49 | return 0; 50 | } 51 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /08condVar/zem.c: -------------------------------------------------------------------------------- 1 | #include "xerrori.h" 2 | #define QUI __LINE__,__FILE__ 3 | 4 | 5 | // Realizzazione di un semaforo usando mutex+condition variable 6 | 7 | // un semaforo si può realizzare con mutex + condition var 8 | // come mostrato qui sotto. Notate che otteniamo un semaforo 9 | // che supporta incrementi e decrementi anche maggiori di 1 10 | 11 | // l'operazione di decremento si blocca se porterebbe 12 | // il valore del semaforo sotto zero 13 | 14 | 15 | // struttura rappresentante il semaforo 16 | typedef struct { 17 | int tot; // valore del semaforo, non deve mai diventare negativo 18 | pthread_cond_t cond; // condition variable 19 | pthread_mutex_t mutex; // mutex associato alla condition variable 20 | } zem; 21 | 22 | 23 | // inzializza semaforo al valore q 24 | // deve essere chiamata (una volta sola!) prima di up e down 25 | void zem_init(zem *z, int q) 26 | { 27 | assert(q>=0); 28 | z->tot = q; 29 | xpthread_cond_init(&z->cond,NULL,QUI); 30 | xpthread_mutex_init(&z->mutex,NULL,QUI); 31 | } 32 | 33 | // analoga alla sem_wait (operazione P di Dijkstra) 34 | void zem_down(zem *z, int q) 35 | { 36 | assert(q>0); 37 | pthread_mutex_lock(&z->mutex); 38 | while(z->tot-q<0) 39 | pthread_cond_wait(&z->cond,&z->mutex); 40 | z->tot -= q; 41 | pthread_mutex_unlock(&z->mutex); 42 | } 43 | 44 | // analoga alla sem_post (operazione V di Dijkstra) 45 | void zem_up(zem *z, int q) 46 | { 47 | assert(q>0); 48 | pthread_mutex_lock(&z->mutex); 49 | z->tot+=q; 50 | pthread_cond_broadcast(&z->cond); 51 | pthread_mutex_unlock(&z->mutex); 52 | } 53 | -------------------------------------------------------------------------------- /03assembler/strcmp.c: -------------------------------------------------------------------------------- 1 | #define _GNU_SOURCE // avverte che usiamo le estensioni GNU 2 | #include // permette di usare scanf printf etc ... 3 | #include // conversioni stringa/numero exit() etc ... 4 | #include // gestisce tipo bool (per variabili booleane) 5 | #include // permette di usare la funzione assert 6 | #include // funzioni di confronto/copia/etc di stringhe 7 | #include 8 | 9 | 10 | // stampa un messaggio d'errore e termina il programma 11 | void termina(const char *messaggio); 12 | 13 | // strcmp implementato in arm 14 | int armcmp(char *,char *); 15 | 16 | 17 | // confronta argomenti passati sulla linea di comando 18 | int main(int argc, char *argv[]) 19 | { 20 | if(argc<=2) { 21 | printf("Uso:\t %s s1 s2 [s3 s4 ...]\n",argv[0]); 22 | return 1; 23 | } 24 | for(int i=1;i strcmp: %d\n",argv[i],argv[i+1],ris); 28 | ris = armcmp(argv[i],argv[i+1]); 29 | printf("%s vs %s --> armcmp: %d\n",argv[i],argv[i+1],ris); 30 | } 31 | return 0; 32 | } 33 | 34 | // funzione C di confronto stringhe usata come modello 35 | // per la versione ARM 36 | int modello(char *s, char *t) 37 | { 38 | for(int i=0; ;i++) 39 | if(s[i]!=t[i]) 40 | return s[i]-t[i]; 41 | else if(s[i]==0) 42 | return 0; 43 | } 44 | 45 | 46 | 47 | void termina(const char *messaggio){ 48 | if(errno!=0) perror(messaggio); 49 | else fprintf(stderr,"%s\n", messaggio); 50 | exit(1); 51 | } 52 | 53 | 54 | -------------------------------------------------------------------------------- /01introC/charstr.c: -------------------------------------------------------------------------------- 1 | #define _GNU_SOURCE // avverte che usiamo le estensioni GNU 2 | #include // permette di usare scanf printf etc ... 3 | #include // conversioni stringa/numero exit() etc ... 4 | #include // gestisce tipo bool (per variabili booleane) 5 | #include // permette di usare la funzione assert 6 | #include // funzioni di confronto/copia/etc di stringhe 7 | 8 | // scopo del programma: illustrare il duplice scopo delle 9 | // variabili char e introdurre il concetto di stringa come 10 | // array di caratteri che termina al primo byte uguale a 0 11 | 12 | 13 | // stampa un messaggio d'errore e termina il programma 14 | void termina(char *messaggio) 15 | { 16 | puts(messaggio); 17 | exit(1); 18 | } 19 | 20 | 21 | int main(int argc, char *argv[]) 22 | { 23 | 24 | char a,b; 25 | 26 | // inzializza le due variabili char a e b l'intero 70 27 | // e con il codice ascii del carattere x 28 | a = 70; 29 | b = 'x'; 30 | // stampo ogni char interpretando codice ascii (modificatore %c) 31 | // e come intero (modificatore %d) 32 | printf("a= %c %d, b=%c %d\n",a,a,b,b); 33 | 34 | // creo una copia della stringa "the answer is 42" 35 | char *z = strdup("the answer is 42"); 36 | printf("originale: %s, lunghezza %zd\n",z,strlen(z)); 37 | // sia per la printf() che per la strlen() 38 | // la stringa termina quando si incontra il byte 0 in z[5] 39 | z[5] = 0; 40 | printf("originale: %s, lunghezza %zd\n",z,strlen(z)); 41 | // la strdup esegue una malloc() quindi devo deallocare con free() 42 | free(z); 43 | return 0; 44 | } 45 | 46 | -------------------------------------------------------------------------------- /02struct/parole.c: -------------------------------------------------------------------------------- 1 | #define _GNU_SOURCE // avverte che usiamo le estensioni GNU 2 | #include // permette di usare scanf printf etc ... 3 | #include // conversioni stringa exit() etc ... 4 | #include // gestisce tipo bool 5 | #include // permette di usare la funzione ass 6 | #include // funzioni per stringhe 7 | #include // rischiesto per usare errno 8 | #include 9 | #include "strint.h" 10 | 11 | // Scopo del programma: 12 | // mostrare un altro esempio di ABR 13 | // mostrare l'uso della compilazione separata 14 | 15 | 16 | 17 | // prototipi delle funzioni che appaiono dopo il main() 18 | void termina(const char *messaggio); 19 | 20 | 21 | int main(int argc, char *argv[]) 22 | { 23 | if(argc<2) { 24 | printf("Uso: %s [s1 s2 ...]\n",argv[0]); 25 | exit(1); 26 | } 27 | 28 | // inserisce le stringhe passate sulla linea di comando 29 | // nell'abr associando gli interi 0,1,2,.... 30 | strint *root = NULL; 31 | for(int i=1;i1 2 | @; output: r0=0 se composto, l'input se è primo 3 | 4 | .data 5 | errmsg: .string "Input non valido (primo)" 6 | 7 | .text 8 | .global primo @; rende il simbolo primo visibile da altri file 9 | .type primo, %function @; necessario per qemu-arm 10 | 11 | primo: cmp r0, #2 @; calcola r0-2 12 | blt stop @; r0<2 errore 13 | bne not2 @; se r0!=2 continua 14 | mov pc, lr @; altrimenti return 2 15 | not2: and r1, r0, #1 @; r1 = r0 & 1 = r0%2 16 | cmp r1, #0 @; r0 e' pari? 17 | bne odd @; se r0 e' dispari continua 18 | nonpr: mov r0, #0 19 | end: mov pc,lr @; return 0 20 | odd: mov r1, #3 @; for(r1=3;r1*r1 <= r0; r1 +=2) 21 | loop: mul r3,r1,r1 22 | cmp r3,r0 @; se r1*r1 > r0 23 | bhi end @; return r0 24 | @; calcolo resto r3 = r0%r1 per sottrazioni successive (inefficiente) 25 | mov r3,r0 26 | resto1: cmp r3,r1 27 | blo resto2 @; se r3 // permette di usare scanf printf etc ... 3 | #include // conversioni stringa/numero exit() etc ... 4 | #include // gestisce tipo bool (per variabili booleane) 5 | #include // permette di usare la funzione assert 6 | #include // funzioni di confronto/copia/etc di stringhe 7 | #include // rischiesto per usare errno 8 | 9 | 10 | // scopo del programma: 11 | // mostrare l'uso di asprintf per concatenare stringhe 12 | // delegando l'allocazione della stringa destinazione 13 | 14 | 15 | // stampa un messaggio d'errore su stderr e termina il programma 16 | void termina(const char *messaggio); 17 | 18 | 19 | int main(int argc, char *argv[]) 20 | { 21 | int a; 22 | char *z=NULL; 23 | puts("Inserisci un numero e uno stringa"); 24 | int e = scanf("%d %ms",&a,&z); 25 | if(e!=2) termina("Errore scanf"); 26 | 27 | // per i=1..n crea i file nome.i.txt 28 | // nell'iesimo file scrivo l'intero i in formato testo 29 | for(int i=1;i<=a;i++) { 30 | char *nome=NULL; 31 | int e = asprintf(&nome,"%s.%d.txt",z,i); 32 | if(e== -1) 33 | termina("Allocazione in asprintf fallita"); 34 | // crea nome file 35 | fprintf(stderr, "Ora apro il file: %s\n",nome); 36 | // apre file 37 | FILE *f =fopen(nome,"wt"); 38 | // scrivo i dentro il file 39 | fprintf(f,"%d\n",i); 40 | // chiudo file e dealloco la stringa nome 41 | fclose(f); 42 | free(nome); 43 | } 44 | 45 | // libero memoria allocata da scanf 46 | free(z); 47 | 48 | return 0; 49 | } 50 | 51 | 52 | void termina(const char *messaggio) 53 | { 54 | perror(messaggio); 55 | exit(1); 56 | } 57 | 58 | -------------------------------------------------------------------------------- /09processi/shm_cons.c: -------------------------------------------------------------------------------- 1 | // esempio produttore/consumatore tra processi 2 | // utilizzando memoria condivisa e named semaphores 3 | // processo consumatore 4 | #include "xerrori.h" 5 | 6 | #define QUI __LINE__,__FILE__ 7 | #define Buf_size 10 8 | #define Shm "/my_shm" 9 | #define Sem_items "/my_items" 10 | #define Sem_slots "/my_slots" 11 | 12 | 13 | 14 | int main(int argc,char *argv[]) 15 | { 16 | if(argc!=1) { 17 | fprintf(stderr,"Uso\n\t%s\n", argv[0]); 18 | exit(1); 19 | } 20 | 21 | // richiede che il produttore abbia già creato i semafori 22 | // e la memoria condivisa per il buffer 23 | // e che essi siano visibili in /dev/shm 24 | 25 | // ---- apertura buffer prod-cons in memoria condivisa 26 | int shm_size = Buf_size*sizeof(int); 27 | int fd = xshm_open(Shm,O_RDWR, 0,QUI); 28 | xftruncate(fd, shm_size, QUI); 29 | int *b = simple_mmap(shm_size,fd, QUI); 30 | close(fd); // dopo mmap e' possibile chiudere il file descriptor 31 | 32 | // ---- apertura semafori named: i semafori devono esistere 33 | // e per questo motivo non specifico mode e valore iniziale 34 | // e di conseguenza non uso xsem_open() 35 | sem_t *free_slots = sem_open(Sem_slots,0); 36 | sem_t *data_items = sem_open(Sem_items,0); 37 | if(free_slots==NULL || data_items==NULL) 38 | xtermina("Non riesco ad aprire i semafori",QUI); 39 | 40 | // loop consumatore 41 | int cindex = 0; 42 | while(true) { 43 | xsem_wait(data_items,QUI); 44 | int d = b[cindex%Buf_size]; 45 | cindex++; 46 | xsem_post(free_slots,QUI); 47 | printf("Item %d read\n",d); 48 | if(d <0) break; 49 | } 50 | 51 | // unmap memoria condivisa e chiude i semafori 52 | xmunmap(b,shm_size,QUI); 53 | xsem_close(data_items,QUI); 54 | xsem_close(free_slots,QUI); 55 | return 0; 56 | } 57 | -------------------------------------------------------------------------------- /01introC/astringhe.c: -------------------------------------------------------------------------------- 1 | #define _GNU_SOURCE // avverte che usiamo le estensioni GNU 2 | #include // permette di usare scanf printf etc ... 3 | #include // conversioni stringa/numero exit() etc ... 4 | #include // gestisce tipo bool (per variabili booleane) 5 | #include // permette di usare la funzione assert 6 | #include // funzioni di confronto/copia/etc di stringhe 7 | 8 | // Scopo del programma: 9 | // mostrare la costruzione e deallocazione di 10 | // un array di stringhe 11 | 12 | 13 | // stampa un messaggio d'errore e termina il programma 14 | void termina(char *messaggio) 15 | { 16 | perror(messaggio); 17 | exit(1); 18 | } 19 | 20 | // esegue una copia della stringa s 21 | // e ne ribalta i carattero 22 | char *copia_ribalta(const char *s) 23 | { 24 | // crea copia 25 | char *t = strdup(s); 26 | // ribalta caratteri 27 | for(int i=0;i { 6 | Nodo n1, n2; 7 | double weight; 8 | 9 | public Arco(Nodo n1,Nodo n2, double w){ 10 | this.n1=n1; 11 | this.n2=n2; 12 | this.weight=w; 13 | } 14 | 15 | public boolean stessi_estremi(Arco a) { 16 | if(n1.equals(a.n1) && n2.equals(a.n2)) 17 | return true; 18 | if(n1.equals(a.n2) && n2.equals(a.n1)) 19 | return true; 20 | return false; 21 | } 22 | 23 | public Nodo altro_estremo(Nodo n) { 24 | if(n.equals(n1)) return n2; 25 | if(n.equals(n2)) return n1; 26 | throw new IllegalArgumentException("nodo non estremo dell'arco"); 27 | } 28 | 29 | /** Confronta due archi sulla base del peso. Il confronto è poi esteso ai nodi 30 | * utilizzando l'ordinamento naturale delle etichette dei nodi. 31 | * La soluzione non è completamente pulita: sarebbe preferibile 32 | * richiedere che i nodi implementino l'interfaccia Comparable 33 | * e usare il metodo compareTo di Nodo, ma questo richiederebbe di 34 | * utilizzare i tipi generici in maniera non banale. 35 | * */ 36 | public int compareTo(Arco a) { 37 | if(weight < a.weight) return -1; 38 | if (weight > a.weight) return 1; 39 | // i pesi sono uguali confrontiamo gli estremi 40 | if(n1.etichetta().compareTo(a.n1.etichetta())!=0) 41 | return n1.etichetta().compareTo(a.n1.etichetta()); 42 | return n2.etichetta().compareTo(a.n2.etichetta()); 43 | } 44 | 45 | public boolean equals(Object o) { 46 | if(o instanceof Arco) { 47 | Arco a = (Arco) o; 48 | return n1.equals(a.n1) && n2.equals(a.n2) && weight==a.weight; 49 | } 50 | return false; 51 | } 52 | 53 | public String toString() { 54 | return String.format("%s <= %6.2f => %s",n1.etichetta(),weight, n2.etichetta()); 55 | } 56 | 57 | } -------------------------------------------------------------------------------- /07threads/makefile: -------------------------------------------------------------------------------- 1 | # definizione del compilatore e dei flag di compilazione 2 | # che vengono usate dalle regole implicite 3 | CC=gcc 4 | CFLAGS=-std=c11 -Wall -g -O -pthread 5 | LDLIBS=-lm -pthread 6 | 7 | 8 | # su https://www.gnu.org/software/make/manual/make.html#Implicit-Rules 9 | # sono elencate le regole implicite e le variabili 10 | # usate dalle regole implicite 11 | 12 | # Variabili automatiche: https://www.gnu.org/software/make/manual/make.html#Automatic-Variables 13 | # nei comandi associati ad ogni regola: 14 | # $@ viene sostituito con il nome del target 15 | # $< viene sostituito con il primo prerequisito 16 | # $^ viene sostituito con tutti i prerequisiti 17 | 18 | # elenco degli eseguibili da creare 19 | EXECS=contaprimi.out tabella_primi.out primi_file.out threadSort.out somma_primi_files.out pmergesort.out atcontaprimi.out 20 | 21 | # primo target: gli eseguibili sono precondizioni 22 | # quindi verranno tutti creati 23 | all: $(EXECS) 24 | 25 | # secondo target che genera gli eseguibili primi_files e primi_barrier 26 | # viene invocato invece di all se si scrive 27 | # "make primi" sulla linea di comando 28 | primi: primi_barrier.out primi_files.out 29 | 30 | 31 | # regola per la creazione degli eseguibili utilizzando xerrori.o 32 | %.out: %.o xerrori.o 33 | $(CC) $(LDFLAGS) -o $@ $^ $(LDLIBS) 34 | 35 | # regola per la creazione di file oggetto che dipendono da xerrori.h 36 | %.o: %.c xerrori.h 37 | $(CC) $(CFLAGS) -c $< 38 | 39 | primi_barrier.o: primi_files.c xerrori.h 40 | $(CC) $(CFLAGS) -o $@ -c $< -D USE_BARRIER 41 | 42 | 43 | # esempio di target che non corrisponde a una compilazione 44 | # ma esegue la cancellazione dei file oggetto e degli eseguibili 45 | clean: 46 | rm -f *.o $(EXECS) 47 | 48 | # crea file zip della lezione 49 | zip: 50 | zip threads.zip *.c *.h *.py makefile 51 | 52 | -------------------------------------------------------------------------------- /01introC/parametri.c: -------------------------------------------------------------------------------- 1 | #define _GNU_SOURCE // avverte che usiamo le estensioni GNU 2 | #include // permette di usare scanf printf etc ... 3 | #include // conversioni stringa/numero exit() etc ... 4 | #include // gestisce tipo bool (per variabili booleane) 5 | #include // permette di usare la funzione assert 6 | #include // funzioni di confronto/copia/etc di stringhe 7 | 8 | // da compilare con: 9 | // gcc -std=c11 -Wall -O -g -o parametri parametri.c 10 | 11 | 12 | // Nota: per eseguire le stampe di interi e puntatori 13 | // questi vengono tutti convertiti in long e 14 | // stampati usando il formato %ld in printf 15 | // (%ld si usa infatti per stamnpare i long) 16 | 17 | 18 | // funzione che incrementa di 1 un parametro 19 | // passato per valore 20 | int incrementa1(int z) 21 | { 22 | printf("incrementa1: z si trova nella posizione %ld e vale %ld\n", 23 | (long) &z, (long )z); 24 | z +=1; 25 | return 0; 26 | } 27 | 28 | // funzione che incrementa di 1 un parametro 29 | // passato per riferimento attraverso un puntatore 30 | int incrementa1p(int *p) 31 | { 32 | printf("incrementa1p: p si trova nella posizione %ld e vale %ld\n", 33 | (long) &p, (long) p); 34 | *p +=1; 35 | return 0; 36 | } 37 | 38 | 39 | int main(int argc, char *argv[]) 40 | { 41 | int n =5; 42 | 43 | printf("main 1: n si trova nella posizione %ld e vale %ld\n", 44 | (long) &n, (long )n); 45 | incrementa1(n); // chiamata per valore: non ha effetto su n 46 | printf("main 2: n si trova nella posizione %ld e vale %ld\n", 47 | (long) &n, (long )n); 48 | incrementa1p(&n); // chiamata per riferimento: modifica n 49 | printf("main 3: n si trova nella posizione %ld e vale %ld\n", 50 | (long) &n, (long )n); 51 | return 0; 52 | } 53 | -------------------------------------------------------------------------------- /01introC/somma.c: -------------------------------------------------------------------------------- 1 | #define _GNU_SOURCE // avverte che usiamo le estensioni GNU 2 | #include // permette di usare scanf printf etc ... 3 | #include // conversioni stringa/numero exit() etc ... 4 | #include // gestisce tipo bool (per variabili booleane) 5 | #include // permette di usare la funzione assert 6 | #include // funzioni di confronto/copia/etc di stringhe 7 | 8 | // le istruzioni qui sopra le spieghiamo più avanti 9 | 10 | // da compilare con: 11 | // gcc -std=c11 -Wall -O -g -o somma somma.c 12 | 13 | 14 | // Scopo del programma: 15 | // legge un intero N da tastiera 16 | // crea un array di N int 17 | // legge N interi mettendoli nell'array 18 | // calcola la somma degli elementi dell'array 19 | // stampa la somma 20 | 21 | int main(int argc, char *argv[]) 22 | { 23 | int n; // definisco variabile intera di nome n 24 | 25 | // spiego cosa voglio leggere e lo leggo con scanf 26 | puts("Inserisci il numero di elementi: "); 27 | int e; 28 | scanf("%d",&n); // il motivo della & lo vedremo più avanti 29 | // controlli sulla lettura 30 | if(e!=1) { 31 | puts("Valore non trovato"); 32 | exit(1); 33 | } 34 | if(n<=0) { 35 | puts("Il numero di elementi deve essere positivo"); 36 | exit(2); 37 | } 38 | 39 | // crea e riempi array 40 | int a[n]; 41 | for(int i=0; i // permette di usare scanf printf etc ... 3 | #include // conversioni stringa/numero exit() etc ... 4 | #include // gestisce tipo bool (per variabili booleane) 5 | #include // permette di usare la funzione assert 6 | #include // funzioni di confronto/copia/etc di stringhe 7 | 8 | // Nota: per compilare questo programma è necessario il 9 | // define iniziale di _GNU_SOURCE che deve necessariamente 10 | // precedere tutti gli include 11 | 12 | 13 | // Scopo del programma: 14 | // il funzionamento dell'array argv contenente i parametri 15 | // passati sulla linea di comando 16 | // mostrare la differenza nel copiare il puntatore e copiare 17 | // tutti i singoli caratteri della stringa 18 | 19 | // stampa un messaggio d'errore e termina il programma 20 | void termina(char *messaggio) 21 | { 22 | puts(messaggio); 23 | exit(1); 24 | } 25 | 26 | 27 | int main(int argc, char *argv[]) 28 | { 29 | 30 | // stampo gli elementi di argv[] come stringhe 31 | for(int i=0;i 5 | 6 | #define QUI __LINE__,__FILE__ 7 | #define Buf_size 10 8 | #define Shm "/my_shm" 9 | #define Sem_items "/my_items" 10 | #define Sem_slots "/my_slots" 11 | 12 | 13 | 14 | int main(int argc,char *argv[]) 15 | { 16 | if(argc!=2) { 17 | fprintf(stderr,"Uso\n\t%s num_items\n", argv[0]); 18 | exit(1); 19 | } 20 | // conversione input 21 | int n= atoi(argv[1]); 22 | 23 | // ---- creazione buffer prod-cons in memoria condivisa 24 | int shm_size = Buf_size*sizeof(int); 25 | int fd = xshm_open(Shm,O_RDWR | O_CREAT, 0666,QUI); 26 | xftruncate(fd, shm_size, QUI); 27 | int *b = simple_mmap(shm_size,fd, QUI); 28 | close(fd); // dopo mmap e' possibile chiudere il file descriptor 29 | // ---- creazione semafori named 30 | sem_t *free_slots = xsem_open(Sem_slots,O_CREAT|O_EXCL,0666,Buf_size,QUI); 31 | sem_t *data_items = xsem_open(Sem_items,O_CREAT|O_EXCL,0666,0,QUI); 32 | // non devo usare unlink qui altrimenti il consumatore non 33 | // non vede memoria condivisa e semafori 34 | 35 | 36 | // loop produttore 37 | int pindex = 0; 38 | for(int j=1;j<=n;j++) { 39 | xsem_wait(free_slots,QUI); 40 | b[pindex%Buf_size] = j; 41 | pindex++; 42 | xsem_post(data_items,QUI); 43 | printf("Item %d written\n",j); 44 | } 45 | // valore di terminazione 46 | xsem_wait(free_slots,QUI); 47 | b[pindex%Buf_size] = -1; 48 | pindex++; 49 | xsem_post(data_items,QUI); 50 | printf("Item %d written\n",-1); 51 | 52 | // prenota cancellazione di shm e sem 53 | xsem_unlink(Sem_items,QUI); 54 | xsem_unlink(Sem_slots,QUI); 55 | xshm_unlink(Shm,QUI); 56 | 57 | // unmap memoria condivisa e chiude i semafori 58 | xmunmap(b,shm_size,QUI); 59 | xsem_close(data_items,QUI); 60 | xsem_close(free_slots,QUI); 61 | return 0; 62 | } 63 | -------------------------------------------------------------------------------- /01introC/scanf.c: -------------------------------------------------------------------------------- 1 | #define _GNU_SOURCE // avverte che usiamo le estensioni GNU 2 | #include // permette di usare scanf printf etc ... 3 | #include // conversioni stringa/numero exit() etc ... 4 | #include // gestisce tipo bool (per variabili booleane) 5 | #include // permette di usare la funzione assert 6 | #include // funzioni di confronto/copia/etc di stringhe 7 | #include // rischiesto per usare errno 8 | 9 | 10 | // scopo del programma: 11 | // mostrare le opzioni di come leggere delle stringhe con 12 | // scanf (e simili, tipo fscanf) 13 | // Fare riferimento ai lucidi letturaStringhe.pdf 14 | 15 | // Ricordare sempre che l'uso di scanf("%s"...) è un'operazione 16 | // a rischio di buffer overflow in quanto 17 | // è possibile scrivere in zone esterne a quelle allocate al programma 18 | 19 | 20 | // stampa un messaggio d'errore su stderr e termina il programma 21 | void termina(const char *messaggio); 22 | 23 | 24 | int main(int argc, char *argv[]) 25 | { 26 | int a=1; 27 | char s[12]; 28 | char *z=NULL; 29 | puts("Inserisci un numero e due stringhe"); 30 | int e = scanf("%d %11s %ms",&a,s,&z); 31 | if(e!=3) termina("Errore scanf"); 32 | 33 | // %11s garantisce che vengono letti al più 12 caratteri (11+\0) 34 | // e quindi rimaniamo dentro s[12] 35 | 36 | // %ms delega il compito di allocare la memoria a scanf 37 | // devo ricordarmi il passaggio per riferimento 38 | // e di eseguire la free() quando la stringa non è più necessaria 39 | 40 | printf("a=%d,s=%s,z=%s\n",a,s,z); 41 | 42 | // libero memoria allocata da scanf 43 | free(z); 44 | 45 | return 0; 46 | } 47 | 48 | 49 | 50 | void termina(const char *messaggio) 51 | { 52 | // se errno!=0 oltre al mio messaggio stampa il messaggio 53 | // associato alla variabile globale errno 54 | // utilizzando la funzione di libreria perror() 55 | if(errno!=0) perror(messaggio); 56 | // altrimenti stampa solo il mio messaggio 57 | else fprintf(stderr,"%s\n", messaggio); 58 | exit(1); 59 | } 60 | 61 | -------------------------------------------------------------------------------- /08condVar/makefile: -------------------------------------------------------------------------------- 1 | # definizione del compilatore e dei flag di compilazione 2 | # che vengono usate dalle regole implicite 3 | CC=gcc 4 | CFLAGS=-std=c11 -Wall -g -O -pthread 5 | LDLIBS=-lm -lrt -pthread 6 | 7 | 8 | # su https://www.gnu.org/software/make/manual/make.html#Implicit-Rules 9 | # sono elencate le regole implicite e le variabili 10 | # usate dalle regole implicite 11 | 12 | # Variabili automatiche: https://www.gnu.org/software/make/manual/make.html#Automatic-Variables 13 | # nei comandi associati ad ogni regola: 14 | # $@ viene sostituito con il nome del target 15 | # $< viene sostituito con il primo prerequisito 16 | # $^ viene sostituito con tutti i prerequisiti 17 | 18 | # elenco degli eseguibili da creare 19 | EXECS=heap.out rw.out somma_primi_files.out stack.out 20 | PC_EXECS=pctest.out pctestCV.out pctestC11.out pctestC11CV.out 21 | 22 | 23 | # primo target: gli eseguibili sono precondizioni del target 24 | # quindi verranno tutti creati 25 | all: $(EXECS) 26 | 27 | # dove versioni di prod/con con semafori oppure condvar 28 | pctests: $(PC_EXECS) 29 | 30 | 31 | # regola per la creazione degli eseguibili utilizzando xerrori.o 32 | %.out: %.o xerrori.o 33 | $(CC) $(LDFLAGS) -o $@ $^ $(LDLIBS) 34 | 35 | # regola per la creazione di file oggetto che dipendono da xerrori.h 36 | %.o: %.c xerrori.h 37 | $(CC) $(CFLAGS) -c $< 38 | 39 | # compila pctest.c con opzione -O3 per ottimizzare la velocità 40 | pctest.o: pctest.c xerrori.h 41 | $(CC) $(CFLAGS) -O3 -c $< -o $@ 42 | 43 | # come sopra ma definisce la costante USACV quindi vengono 44 | # usate le CV invece dei semafori nel paradigma prod-cons 45 | pctestCV.o: pctest.c xerrori.h 46 | $(CC) $(CFLAGS) -O3 -c $< -o $@ -DUSACV 47 | 48 | 49 | # versione C11 dei precedenti 50 | pctestC11.out: pctestC11.c semC11.h 51 | $(CC) $(CFLAGS) -O3 $< -o $@ 52 | pctestC11CV.out: pctestC11.c semC11.h 53 | $(CC) $(CFLAGS) -O3 $< -o $@ -DUSACV 54 | 55 | 56 | 57 | 58 | 59 | # esempio di target che non corrisponde a una compilazione 60 | # ma esegue la cancellazione dei file oggetto e degli eseguibili 61 | clean: 62 | rm -f *.o $(EXECS) $(PC_EXECS) 63 | 64 | 65 | -------------------------------------------------------------------------------- /02struct/qsortstr.c: -------------------------------------------------------------------------------- 1 | /* ********************************************************* 2 | * Esempio di uso di qsort per ordinare array di interi 3 | * ********************************************************* */ 4 | #include // permette di usare scanf printf etc ... 5 | #include // conversioni stringa/numero rand() abs() exit() etc ... 6 | #include // gestisce tipo bool (per variabili booleane) 7 | #include // permette di usare la funzione assert 8 | #include // richiesto per usare errno 9 | #include 10 | 11 | // stampa un messaggio di errore e termina 12 | void termina(const char *messaggio); 13 | 14 | 15 | // funzione di confronto, con i tipi corretti 16 | // necessita del casting al tipo __compar_fn_t 17 | // nella chiamata del qsort altrimenti il compilatore 18 | // da un warning 19 | int confronta_str(char **a, char **b) 20 | { 21 | return strcmp(*a,*b); 22 | } 23 | 24 | int main(int argc, char *argv[]) 25 | { 26 | if(argc<=2) { // input sulla linea di comando non corretto 27 | printf("Uso: %s str1 str2 str3 ... strk \n",argv[0]); 28 | return 1; 29 | } 30 | int n = argc-1; // Numero argomenti linea di comando 31 | 32 | char **a = &argv[1]; 33 | 34 | // stampo array 35 | for(int i=0;i // permette di usare scanf printf etc ... 3 | #include // conversioni stringa exit() etc ... 4 | #include // gestisce tipo bool 5 | #include // permette di usare la funzione ass 6 | #include // funzioni per stringhe 7 | #include // rischiesto per usare errno 8 | #include 9 | 10 | 11 | // definizione struct che rappresenta 12 | // una città con nome, e coordinate 13 | // + campi left/right per costruire l'albero 14 | typedef struct strint { 15 | char *s; 16 | int n; 17 | struct strint *left, *right; 18 | } strint; 19 | 20 | 21 | void strint_stampa(const strint *a, FILE *f); 22 | strint *strint_crea(char *w, int v); 23 | void strint_distruggi(strint *a); 24 | // stampa tutti gli elementi dell'albero 25 | // che ha come radice root 26 | void abr_strint_stampa(const strint *root, FILE *f); 27 | // stampa tutti gli elementi dell'albero 28 | // che ha come radice root 29 | // facendo una visita in preorder 30 | // il parametro depth è la profondita di root 31 | void abr_strint_stampa_preorder(const strint *root, FILE *f, int depth); 32 | 33 | // distrugge tutti gli elementi dell'ABR con radice root 34 | void abr_strint_distruggi(strint *root); 35 | 36 | 37 | // inserisci il nuovo nodo "c" dentro l'albero 38 | // con radice "root", non inserisce se c 39 | // è già presente, restituisce la root 40 | // del nuovo albero contenente anche "c" 41 | strint *abr_inserisci(strint *root, strint *c); 42 | 43 | // cerca la stringa w dentro l'abr con radice root 44 | // restituisce il puntatore al nodo se trovata 45 | // altrimenti NULL 46 | strint *abr_ricerca(strint *root, char *w); 47 | 48 | // dato un abr di radice root restituisce 49 | // la sua altezza = numero di livelli = 50 | // profondità massima di una foglia 51 | int abr_altezza(strint *root); 52 | 53 | // conta il numero di nodi dell'albero 54 | int abr_strint_totnodi(const strint *root); 55 | 56 | // calcola la somma dei valori nei nodi dell'albero 57 | int abr_strint_sommanodi(const strint *root); 58 | 59 | 60 | 61 | -------------------------------------------------------------------------------- /06python/argomenti.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | """ 3 | Esempi che mostrano l'uso di argomenti posizionali e keyword 4 | 5 | Vedere la documentazione delle principali funzioni 6 | https://docs.python.org/3/library/functions.html 7 | """ 8 | 9 | 10 | # esempio di funzione che esegue una somma o un prodotto 11 | def somma(a,b): 12 | return a+b 13 | 14 | # generalizzazione che accetta un numero 15 | # qualsiasi di argomenti posizionali 16 | def multi_somma(a,*altri): 17 | print("altri:", altri) 18 | for b in altri: 19 | a += b 20 | return a 21 | 22 | # questa è problematica perchè può essere chiamata 23 | # senza argomenti 24 | def multi_sommaNO(*tutti): 25 | a = tutti[0] 26 | for b in tutti[1:]: 27 | a += b 28 | return a 29 | 30 | # funzione con anche due keyword argument 31 | # per ogni keyword devo specificare il valore di default 32 | def xsomma(a,b,segno = 1, potenza = 0): 33 | return segno*(a+b)*10**potenza 34 | 35 | # metodi validi per chiamare la funzione 36 | # xsomma(2,3) -> 5 (usa i valori di default) 37 | # xsomma(2,3,-1) -> -5 (usa il valore di default per potenza) 38 | # xsomma(2,3,-1,2) -> -500 (usa i valori passati) 39 | # xsomma(2,3,segno=-1, potenza=2) -> -500 (come sopra) 40 | # xsomma(2,3,potenza=2) -> 500 (usa il valore di default per segno) 41 | 42 | # funzione che accetta un numero arbitrario di argomenti 43 | # posizionali, ora quelli keyword devono essere 44 | # forniti con la keyword 45 | def multi_xsomma(a,*altri,segno = 1, potenza = 0): 46 | for b in altri: 47 | a += b 48 | return segno*a*10**potenza 49 | 50 | # accetta un numero qualsiasi di argomenti keywords 51 | def multi_xsomma2(a,*altri,segno = 1, **kwargs): 52 | print("diz:", kwargs) 53 | for b in altri: 54 | a += b 55 | a = segno*a 56 | if "potenza" in kwargs: 57 | a*= 10**kwargs["potenza"] 58 | if "soglia" in kwargs: 59 | if a> kwargs["soglia"]: 60 | a = kwargs["soglia"] 61 | return a 62 | 63 | # per finire: uso di * e ** per scompattare liste e dizionari 64 | lista = [2,3,5,7] 65 | diz = {"segno":-1, "potenza":3} 66 | # esempio: 67 | # multi_xsomma(*lista,**diz) 68 | 69 | 70 | -------------------------------------------------------------------------------- /03assembler/array_primi.s: -------------------------------------------------------------------------------- 1 | @; funzione che alloca e restituisce array dei primi fino a n 2 | @; input r0: n 3 | #; r1: *num indirizzo di dove scrivere la lunghezza dell'array 4 | @; output r0: indirizzo array restituito 5 | 6 | .data 7 | err_nomem: .string "out of mem" 8 | 9 | .text 10 | .global array_primi 11 | .type array_primi, %function 12 | 13 | array_primi: 14 | cmp r0, #2 @; calcola r0-2 15 | blt stop1 @; r0<2 errore 16 | push {r1,r4,r5,r6,r7,r8,lr} 17 | mov r6,r0 @; r6 non viene modificato nelle chiamate 18 | @; allochiamo array sufficientemente grande r7=(n+1)/2 19 | add r0,#1 20 | lsr r7,r0,#1 @; r7 dimensione array in int 21 | @; chiamiamo malloc 22 | lsl r0,r7,#2 @; numero di byte (moltiplico r7 per 4) 23 | bl malloc 24 | cmp r0,#0 @; controlla se r0 = NULL 25 | beq stop2 26 | @; inizio a riempire array 27 | mov r4,r0 @; salvo inizio array in r4 (r0 serve per le chiamate) 28 | mov r0,#2 @; salvo il valore di 2 nell'array 29 | str r0,[r4] 30 | mov r5,#1 @; numero elementi messi in array 31 | @; loop for(r0=3;r0<=n;r0+=2) 32 | mov r0,#1 33 | loop: 34 | add r0,#2 35 | cmp r0,r6 36 | bhi finito @; r0>n 37 | mov r8,r0 38 | bl primo @; chiamata al mio test di primalità 39 | cmp r0,#0 40 | mov r0,r8 41 | beq loop @; iterazione successiva 42 | str r0,[r4,r5,lsl #2] @; salva r0 43 | add r5,#1 @; incremento messi 44 | @; assert messi<= r7 (dimensione array) 45 | cmp r5,r7 46 | bhi stopa 47 | b loop 48 | 49 | finito: @; realloc 50 | mov r0,r4 51 | lsl r1, r5,#2 52 | bl realloc @; il nuovo indirizzo è in r0 53 | cmp r0,#0 54 | beq stop2 55 | @; return 56 | mov r2,r5 57 | pop {r1,r4,r5,r6,r7,r8,lr} @; recupero i valori 58 | str r2,[r1] @; salvo numero di elementi in *num 59 | mov pc, lr @; return al main 60 | 61 | stop1: 62 | mov r0,#2 63 | b exit @; chiama exit(2) 64 | stopa: 65 | mov r0,#3 66 | b exit @; chiama exit(3) 67 | stop2: 68 | ldr r0,=err_nomem 69 | b termina @; chiama termina nel file .c che esegue exit(1) 70 | -------------------------------------------------------------------------------- /01introC/sommad.c: -------------------------------------------------------------------------------- 1 | #define _GNU_SOURCE // avverte che usiamo le estensioni GNU 2 | #include // permette di usare scanf printf etc ... 3 | #include // conversioni stringa/numero exit() etc ... 4 | #include // gestisce tipo bool (per variabili booleane) 5 | #include // permette di usare la funzione assert 6 | #include // funzioni di confronto/copia/etc di stringhe 7 | 8 | // le istruzioni qui sopra le spieghiamo più avanti 9 | 10 | // da compilare con: 11 | // gcc -std=c11 -Wall -O -g -o sommad sommad.c 12 | 13 | // Il programma esegue esattamente le stesse operazioni di somma.c 14 | // ma utilizza un array "dinamico" ottenuto con malloc 15 | 16 | // Scopo del programma: 17 | // legge un intero N da tastiera 18 | // crea un array *dinamico* di N int 19 | // legge N interi mettendoli nell'array 20 | // calcola la somma degli elementi dell'array 21 | // stampa la somma 22 | 23 | int main(int argc, char *argv[]) 24 | { 25 | int n; // definisco variabile intera di nome n 26 | 27 | // spiego cosa voglio leggere e lo leggo con scanf 28 | printf("Inserisci il numero di elementi: "); 29 | int e = scanf("%d",&n); // il motivo della & lo vedremo più avanti 30 | // controlli sulla lettura 31 | if(e!=1) { 32 | puts("Valore non trovato"); 33 | exit(1); 34 | } 35 | if(n<=0) { 36 | puts("Il numero di elementi deve essere positivo"); 37 | exit(2); 38 | } 39 | 40 | // prima era solo: int a[n] 41 | // crea un array dinamico e riempi array 42 | int *a; // dichiaro che a sarà usata come array 43 | a = malloc(n*sizeof(int)); 44 | if(a==NULL) { 45 | puts("Malloc fallita"); 46 | exit(3); 47 | } 48 | 49 | for(int i=0;i // permette di usare scanf printf etc ... 3 | #include // conversioni stringa exit() etc ... 4 | #include // gestisce tipo bool 5 | #include // permette di usare la funzione ass 6 | #include // funzioni per stringhe 7 | #include // richiesto per usare errno 8 | 9 | void termina(const char *messaggio); 10 | 11 | 12 | 13 | // main che legge le linee e le spezza al ; 14 | // poi inserisce le stringhe in una lista ordinata 15 | // eseguire passando come argomento sudAmerica.txt 16 | int main(int argc, char *argv[]) 17 | { 18 | 19 | if(argc!=2) { 20 | printf("Uso: %s nomefile\n",argv[0]); 21 | exit(1); 22 | } 23 | FILE *f = fopen(argv[1],"r"); 24 | if(f==NULL) termina("Errore apertura file"); 25 | 26 | // ciclo di lettura dal file f 27 | char *buffer=NULL; // usate da getline() 28 | size_t n=0; // vengono riutilizzate ad ogni iterazione 29 | // legge una linea del file alla volta 30 | while(true) { 31 | //leggi linea dal file salvando contenuto in buffer 32 | ssize_t e = getline(&buffer,&n,f); 33 | if(e<0) { // segnala la fine del file 34 | free(buffer); // dealloco il buffer usato per contenere le linee 35 | break; // esci dal ciclo di lettura 36 | } 37 | // scommentare per vedere cosa ha letto getline() 38 | // fprintf(stderr,"e=%ld n=%zd, buffer=%s",e, n,buffer); 39 | // Legge i primi tre token di buffer 40 | char *s = strtok(buffer,";"); 41 | printf("token 1: %s\n",s); 42 | s = strtok(NULL,";"); // per leggere i token dopo il primo 43 | printf("token 2: %s\n",s); // si passa NULL a strtok 44 | s = strtok(NULL,";"); 45 | printf("token 3: %s\n",s); 46 | } // end while del getline 47 | fclose(f); 48 | return 0; 49 | } 50 | 51 | 52 | 53 | 54 | // stampa su stderr il messaggio che gli passo 55 | // se errno!=0 stampa anche il messaggio d'errore associato 56 | // a errno. dopo queste stampe termina il programma 57 | void termina(const char *messaggio) 58 | { 59 | if(errno==0) 60 | fprintf(stderr,"%s\n",messaggio); 61 | else 62 | perror(messaggio); 63 | exit(1); 64 | } 65 | 66 | 67 | 68 | -------------------------------------------------------------------------------- /03assembler/primi.c: -------------------------------------------------------------------------------- 1 | #define _GNU_SOURCE // avverte che usiamo le estensioni GNU 2 | #include // permette di usare scanf printf etc ... 3 | #include // conversioni stringa/numero exit() etc ... 4 | #include // gestisce tipo bool (per variabili booleane) 5 | #include // permette di usare la funzione assert 6 | #include // funzioni di confronto/copia/etc di stringhe 7 | 8 | 9 | // programma già visto per la costruzione di una tabella di primi 10 | // la differenza rispetto a prima e che la funzione primo() 11 | // è scritta in assembler nel file primo.s 12 | 13 | 14 | 15 | 16 | void termina(char *messaggio) 17 | { 18 | puts(messaggio); 19 | exit(1); 20 | } 21 | 22 | 23 | // dato k restituisco !=0 se e' primo, 0 altrimenti 24 | // realizzata in primo.s 25 | int primo(int k); 26 | 27 | 28 | 29 | // legge un intero N e costruisce array dei primi <=N 30 | int main(int argc, char *argv[]) 31 | { 32 | int n; 33 | 34 | if(argc!=2) { 35 | printf("Uso: %s nmax\n",argv[0]); 36 | return 1; 37 | } 38 | n = atoi(argv[1]); 39 | if(n<2) 40 | termina("L'array che ti interesa è vuoto"); 41 | 42 | int *a; // array che conterrà i primi 43 | int size=10; // dimensione attuale dell'array 44 | int messi=0; // numero di elementi attualmente nell'array 45 | a = malloc(size*sizeof(int)); 46 | if(a==NULL) 47 | termina("Memoria insufficiente"); 48 | 49 | // cerco i numeri primi da 2 a N 50 | for(int i=2;i<=n;i++) { 51 | // se i è primo lo aggiungo ad a[] 52 | if(primo(i)) { 53 | // devo aggiungere i all'array a[] 54 | if(messi==size) { 55 | // ingrandisco l'array 56 | size = size*2; 57 | a = realloc(a,size*sizeof(int)); 58 | if(a==NULL) 59 | termina("realloc fallita"); 60 | } 61 | a[messi] = i; 62 | messi += 1; 63 | } 64 | } 65 | // ho messo tutti gli elementi che mi interesavano 66 | size = messi; 67 | a = realloc(a,size*sizeof(int)); 68 | if(a==NULL) 69 | termina("realloc fallita"); 70 | 71 | // stampo il contenuto dell'array 72 | for(int i=0;i mst() 33 | ``` 34 | che calcola il minimum spanning tree di un grafo mediante l'[algoritmo di Prim](https://en.wikipedia.org/wiki/Prim's_algorithm). L'algoritmo deve restituire la lista degli archi che fanno parte di un minimum spanning tree, o di una minimum spanning forest nel caso il grafo non sia connesso. Testare l'algoritmo sul grafo fornito dalle città italiane. Per gli esperimenti si tenga conto che la distanza (il secondo parametro sulla linea di comando) deve essere almeno 320 Km affinché il grafo risulti connesso. 35 | 36 | Per l'implementazione dell'algoritmo è necessario mantenere l'insieme dei nodi appartenenti all'albero (consiglio usare un `HashSet`) e l'insieme degli archi che collegano un nodo interno all'albero con un nodo all'esterno (consiglio di usare un `TreeSet`, ricordo che la classe `Arco` è `Comparable` con un ordinamento basato sulla lunghezza dell'arco). 37 | 38 | -------------------------------------------------------------------------------- /04fileBinari/write_speed.c: -------------------------------------------------------------------------------- 1 | #define _GNU_SOURCE // avverte che usiamo le estensioni GNU 2 | #include // permette di usare scanf printf etc ... 3 | #include // conversioni stringa/numero exit() etc ... 4 | #include // gestisce tipo bool (per variabili booleane) 5 | #include // permette di usare la funzione assert 6 | #include // funzioni di confronto/copia/etc di stringhe 7 | #include // richiesto per usare errno 8 | // richesti dalla open 9 | #include 10 | #include 11 | #include 12 | #include 13 | // richiesta da time 14 | #include 15 | 16 | // Scopo del programma: 17 | // mostrare la differenza di prestazioni fra fwrite e write 18 | // quando vengono eseguite scritture multiple di pochi byte 19 | // mostrare come si misura il tempo di esecuzione 20 | // di una parte di un programma 21 | 22 | 23 | void termina(const char *messaggio); 24 | 25 | 26 | 27 | int main(int argc, char *argv[]) 28 | { 29 | // verifica siano stati forniti esattamente 2 parametri 30 | if(argc!=2) { 31 | printf("Uso: %s interi_da_scrivere\n",argv[0]); 32 | return 1; 33 | } 34 | // converte il primo parametro in un intero 35 | int n = atoi(argv[1]); 36 | if(n<=0) termina("Il parametro n deve essere positivo"); 37 | 38 | // scrittura con fwrite 39 | time_t start = time(NULL); // numero di secondi da 1/1/1970 40 | FILE *f = fopen("fwrite.out","wb"); 41 | if(f==NULL) termina("Errore apertura file"); 42 | for(int i=0;i // permette di usare scanf printf etc ... 3 | #include // conversioni stringa/numero exit() etc ... 4 | #include // gestisce tipo bool (per variabili booleane) 5 | #include // permette di usare la funzione assert 6 | #include // funzioni di confronto/copia/etc di stringhe 7 | #include // richiesto per usare errno 8 | 9 | // Scopo del programma: 10 | // mostrare come calcolare la dimensione di un file 11 | // e come si legge da un file binario 12 | 13 | 14 | void termina(const char *messaggio); 15 | 16 | 17 | int main(int argc, char *argv[]) 18 | { 19 | // verifica siano stati forniti esattamente 2 parametri 20 | if(argc!=2) { 21 | printf("Uso: %s nome_file\n",argv[0]); 22 | return 1; 23 | } 24 | char *nome_file = argv[1]; 25 | 26 | // apro il file in lettura 27 | FILE *f = fopen(nome_file,"rb"); 28 | if(f==NULL) termina("Apertura file fallita"); 29 | 30 | // leggo tutti gli interi del file e li metto in un array 31 | 32 | // determino la dimensione del file 33 | // per farlo mi metto alla fine del file 34 | int e = fseek(f, 0, SEEK_END); 35 | if(e!=0) termina("Errore fseek"); 36 | // chiedo in che posizione del file sono 37 | long lungfile = ftell(f); 38 | if(lungfile<0) termina("Errore ftell"); 39 | if(lungfile%4!=0) termina("Il file non contiene int32"); 40 | // numero di interi nel file 41 | int n = lungfile/4; 42 | if(n==0) termina("file vuoto"); 43 | // alloca array dove mettere gli interi 44 | int *a = malloc(n*sizeof(*a)); 45 | if(a==NULL) termina("errore malloc"); 46 | rewind(f); // "riavvolgo" il file 47 | // leggo tutti gli interi nell'array a[] 48 | size_t m = fread(a,sizeof(int),n,f); 49 | if(n!=m) termina("errore fread"); 50 | // chiudi il file 51 | if(fclose(f)==EOF) 52 | termina("Errore chiusura file");; 53 | // stampiamo gli interi letti 54 | for(int i=0;i0 && n1>=n0 && p>0); 41 | // creo una pipe di comunicazione dai figli al genitore 42 | int up[2]; // la chiamo up perchè la uso da figli a genitore 43 | xpipe(up,__LINE__,__FILE__); 44 | // generazione dei processi child 45 | for(int i=0;i // permette di usare scanf printf etc ... 3 | #include // conversioni stringa exit() etc ... 4 | #include // gestisce tipo bool 5 | #include // permette di usare la funzione ass 6 | #include // funzioni per stringhe 7 | #include // richiesto per usare errno 8 | 9 | 10 | // Scopo del programma: 11 | // mostrare il funzionamento di getline() e strtok() 12 | // Eseguire passando come argomento persone.txt 13 | 14 | 15 | // prototipo funzione dopo il main 16 | void termina(const char *messaggio); 17 | 18 | 19 | // "elimina" gli spazi in testa a una stringa 20 | // restituisce un puntatore alla prima posizione 21 | // che non è uno spazio 22 | char *elimina_spazi_testa(char s[]) 23 | { 24 | int i=0; 25 | while(s[i]==' ') 26 | i++; 27 | assert(s[i]!=' '); 28 | return &s[i]; 29 | } 30 | 31 | 32 | // main che legge le linee e le spezza al ; 33 | // elimina eventuali spazi iniziali 34 | // e stampa il risultato 35 | int main(int argc, char *argv[]) 36 | { 37 | 38 | if(argc!=2) { 39 | printf("Uso: %s nomefile\n",argv[0]); 40 | exit(1); 41 | } 42 | FILE *f = fopen(argv[1],"r"); 43 | if(f==NULL) termina("Errore apertura file"); 44 | 45 | // ciclo di lettura delle linee del file 46 | char *buffer=NULL; // usata da getline() 47 | size_t n=0; // usata da getline() 48 | while(true) { 49 | //leggi linea dal file 50 | ssize_t e = getline(&buffer,&n,f); 51 | if(e<0) { // se e<0 assumiamo sia finito il file 52 | free(buffer); // dealloco il buffer usato per le linee 53 | break; 54 | } 55 | // esegue la tokenizzazione di buffer: legge primo token 56 | char *s = strtok(buffer,";\n"); 57 | while(s!=NULL) { 58 | s = elimina_spazi_testa(s); // elimina spai in testa 59 | if(strlen(s)>0) printf("Letto: <%s>\n",s); 60 | // legge il prossimo token 61 | s = strtok(NULL,";\n"); 62 | } 63 | } // end while del getline 64 | fclose(f); 65 | return 0; 66 | } 67 | 68 | 69 | 70 | 71 | // stampa su stderr il messaggio che gli passo 72 | // se errno!=0 stampa anche il messaggio d'errore associato 73 | // a errno. dopo queste stampe termina il programma 74 | void termina(const char *messaggio) 75 | { 76 | if(errno==0) 77 | fprintf(stderr,"%s\n",messaggio); 78 | else 79 | perror(messaggio); 80 | exit(1); 81 | } 82 | 83 | 84 | 85 | -------------------------------------------------------------------------------- /10segnali/segnali.c: -------------------------------------------------------------------------------- 1 | #include "xerrori.h" 2 | #define QUI __LINE__,__FILE__ 3 | 4 | 5 | // esempio base di gestione asincrona dei segnali 6 | // cioè utilizzando un handler definito con sigaction 7 | 8 | 9 | // variabili globali utilizzate da main e dal signal handler 10 | volatile sig_atomic_t tot_segnali = 0; 11 | // il perche' della keyword volatile lo abbiamo visto a lezione 12 | volatile sig_atomic_t continua = 1; 13 | 14 | 15 | // funzione che viene invocata quando viene ricevuto 16 | // un segnale USR1 USR2 o INT (Control-C) 17 | void handler(int s) 18 | { 19 | tot_segnali++; 20 | if(s!=SIGUSR1) { 21 | kill(getpid(),SIGUSR1); // manda SIGUSR1 a se stesso 22 | } 23 | // la printf non si dovrebbe usare in un handler 24 | printf("Segnale %d ricevuto dal processo %d\n", s, getpid()); 25 | if(s==SIGUSR2) { 26 | // forza uscita dal loop infinito del main() 27 | continua = 0; 28 | } 29 | } 30 | 31 | 32 | int main(int argc, char *argv[]) 33 | { 34 | // definisce signal handler 35 | struct sigaction sa; 36 | sa.sa_handler = &handler; 37 | // setta sa.sa_mask che è la maschera di segnali da bloccare 38 | // durante l'esecuzione di handler(). 39 | sigfillset(&sa.sa_mask); // tutti i segnali nella maschera ... 40 | // sigdelset(&sa.sa_mask,SIGUSR1); // ... tranne SIGUSR1 41 | sigaction(SIGUSR1,&sa,NULL); // handler per USR1 42 | sigaction(SIGUSR2,&sa,NULL); // stesso handler per USR2 43 | // definisco variabile dove salvo il settaggio attuale per SIGINT 44 | struct sigaction oldsa; 45 | sigaction(SIGINT,&sa,&oldsa); // stesso handler per Control-C 46 | 47 | // visualizza il pid 48 | printf("Se vuoi mandarmi dei segnali il mio pid e': %d\n", getpid()); 49 | 50 | continua = 1; 51 | do { // loop apparentemente senza uscita 52 | sleep(100); // la sleep viene interrotta dai segnali 53 | puts("loop1: svegliato"); 54 | } while(continua!=0); 55 | printf("Ricevuti: %d segnali (uscito primo loop)\n", tot_segnali); 56 | 57 | // rimetti la vecchia gestione di SIGINT 58 | sigaction(SIGINT,&oldsa,NULL); 59 | // ora SIGINT interrompe l'esecuzione come per default 60 | puts("Vecchio SIGINT ripristinato"); 61 | 62 | // rientro nel loop, per uscire serve un altro segnale usr2 63 | // oppure un SIGINT... 64 | continua = 1; 65 | do { // loop apparentemente senza uscita 66 | pause(); // attende un segnale 67 | puts("loop2: svegliato"); 68 | } while(continua); 69 | printf("Ricevuti: %d segnali (secondo loop)\n", tot_segnali); 70 | return 0; 71 | } 72 | 73 | -------------------------------------------------------------------------------- /05java/coppia.java: -------------------------------------------------------------------------------- 1 | import java.util.ArrayList; 2 | 3 | class Coppia { 4 | int x,y; // variabili d'istanza 5 | 6 | // costruttore 7 | Coppia(int x, int y) { 8 | this.x = x; // usiamo this per distinguere tra variabili d'istanza e parametri 9 | this.y = y; 10 | } 11 | // esempio di secondo costruttore che crea la coppia 0,0 12 | // è un esempio di overloading (stesso nome, segnatura diversa) 13 | Coppia() { 14 | x=0; y=0; // l'uso di this qui non è necessario 15 | } 16 | 17 | // crea stringa che rappresenta la coppia 18 | // viene invocato ad esempio da println 19 | public String toString() { 20 | return String.format("(%d,%d)",x,y); 21 | } 22 | 23 | // overriding del metodo equals di Object per confrontare coppie 24 | // sulla base dei valori delle componenti 25 | public boolean equals(Object o) { 26 | if(o == null || !(o instanceof Coppia)) 27 | return false; 28 | Coppia c = (Coppia)o; // casting simile a quello del C 29 | return x==c.x && y==c.y; 30 | } 31 | 32 | // metodo main: crea coppie con i dati dalla linea di comando e le ordina 33 | public static void main(String[] args) { 34 | // controlla che ci siano almeno due argomenti e che siano pari 35 | if(args.length < 2 || args.length% 2!=0) { 36 | System.out.println("Uso: java Coppia x1 y1 x2 y2 ..."); 37 | System.exit(1); 38 | } 39 | 40 | // crea una lista di coppie di interi passati sulla linea di comando 41 | ArrayList lista = new ArrayList(); 42 | for(int i=0; i Math.abs(c1.x-c1.y) - Math.abs(c2.x-c2.y)); 51 | 52 | // esempio più complesso che ordina per differenza crescente 53 | // e a parità di differenza, ordina per x decrescente 54 | // lista.sort((c1,c2) -> { 55 | // int diff1 = Math.abs(c1.x-c1.y); 56 | // int diff2 = Math.abs(c2.x-c2.y); 57 | // if(diff1 != diff2) 58 | // return diff1 - diff2; 59 | // return c2.x - c1.x; 60 | // }); 61 | 62 | // stampa la lista 63 | for(Coppia c: lista) 64 | System.out.println(c); 65 | System.out.println("---- end ----"); 66 | // test del metodo contains: invoca equals di Coppia 67 | Coppia c = new Coppia(2, 3); 68 | System.out.println("c=" + c + " è in lista? " + lista.contains(c)); 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /10segnali/Readme.md: -------------------------------------------------------------------------------- 1 | ## Esercizi 2 | 3 | 4 | ### Alice, Bob con segnali real-time (8/4/25) 5 | 6 | 7 | Si consideri il seguente gioco tra Alice e Bob: si parte da un intero *N*, a turno ogni giocatore può: 8 | 9 | * se *N* pari sottrarre 1 da *N* oppure dimezzarlo 10 | * se *N* è dispari può solo sottrarre 1 (la mossa è forzata) 11 | 12 | vince che raggiunge il valore zero. Ad esempio, se il valore iniziale è 12 una possibile sequenza di gioco è: 13 | 14 | * Bob: 12 -> 6 15 | * Alice: 6 -> 5 16 | * Bob: 5 -> 4 17 | * Alice: 4 -> 2 18 | * Bob: 2 -> 1 19 | * Alice 1 -> 0 e vince 20 | 21 | 22 | Scrivere una coppia di programmi `alice` e `bob` che effettuano un certo numero di partite secondo il seguente schema: 23 | 24 | 1. `alice` chiede all'utente (con `scanf`) un intero non negativo e lo comunica a `bob` con un segnale; 25 | 26 | 2. Se il valore *N* fornito dall'utente è zero entrambi i programmi terminano, altrimenti iniziano a giocare e `bob` esegue la prima mossa 27 | 28 | 3. I programmi devono fare mosse valide (non importa se giocano male) e comunicare la mossa scelta all'avversario utilizzando un segnale (la mossa va comunicata anche quando è forzata) 29 | 30 | 4. Chi riceve la mossa deve verificarne la correttezza e inviare la sua mossa di risposta ancora con un segnale 31 | 32 | 5. Quando la partita finisce ogni programma deve stampare un messaggio `ha vinto Alice` oppure `ha vinto Bob` e poi si torna al punto 1 per una eventuale nuova partita. 33 | 34 | Idealmente i due programmi devono fare sempre mosse valide, accorgersi che la partita è finita e stampare lo stesso messaggio alla fine di ogni partita. 35 | 36 | 37 | Dovete scrivere due sorgenti diversi `alice.c` e `bob.c`; l'utente deve eseguire dalla di comando `alice` che deve far partire `bob` con una `fork` + `exec`; questo è necessario perchè ogni programma deve poter conoscere il `pid` dell'altro per inviare i segnali. Usate i segnali real-time con la funzione `sigqueue(3)` per inviare un intero, e `sigwaitinfo(2)` per la ricezione dei segnali. 38 | 39 | 40 | 41 | ### heap e ctrl-C (8/4/25) 42 | 43 | Modificare il programma `08condVar/heap.c` aggiungendo un thread gestore di segnali tale che quando viene premuto il tasto `ctrl-C` viene fatta un'allocazione di un blocco di 7 unità di memoria che deve essere mantenuto allocato per 5 secondi. Il programma deve essere fatto in modo che successivi invii di `ctrl-C` effettuino successive allocazioni di 7 unità di memoria anche se i precedenti blocchi da 7 non sono ancora stati deallocati (naturalmente l'allocazione può avvenire solo se la memoria è disponibile altrimenti il thread deve rimanere in attesa). 44 | 45 | -------------------------------------------------------------------------------- /03assembler/Readme.md: -------------------------------------------------------------------------------- 1 | ### Utilizzo di un Raspberry Pi per programmare in assembler ARM 2 | 3 | 4 | 1. Installare sul Raspberry il sistema operativo [Raspberry Pi OS](https://www.raspberrypi.com/software/): ho provato anche Ubuntu server ma, oltre ad essere più lento, i programmi non venivano compilati correttamente. Per l'accesso e lo scambio di file con il Raspberry è necessario utilizzare `ssh` seguendo [questa guida](https://www.raspberrypi.com/documentation/computers/remote-access.html). 5 | 6 | 7 | 2. Installare *valgrind* con `sudo apt install valgrind`. Se la versione di *valgrind* è precedente alla 3.17 e segnala errori inesistenti, installate l'ultima versione dal [sito ufficiale](https://valgrind.org/downloads/current.html) seguendo le istruzioni del README. 8 | 9 | 10 | 3. Non ho trovato IDE già configurati per l'assembler ARM; io utilizzo [Geany](https://geany.org/) (solitamente è già istallato) al quale ho aggiunto qualche configurazione specifica per l'assembler. In particolare il file *filetypes.asm* contiene la configurazione per l'highlight delle principali parole chiave e per associare ai tasti F8/F9/shift-F9 i comandi Compile/Build/Make. Andando su *Build->Set build commands* potete ridefinire questi comandi (eventualmente per eseguire la cross compilation). Il file *filetypes.asm* va messo nella directory *~/.config/geany/filedefs*. Il file *bespin2.conf* contiene un tema dark ed è da mettere nella directory *~/.config/geany/colorschemes*. Purtroppo non sono riuscito a fargli capire che i commenti iniziano con `@` e non con `;` per rimediare a questo inizio i commenti con i due caratteri `@;` 11 | 12 | 4. Per testare la compilazione potete usare il file `primi.c` che calcola una tabella di primi utilizzando un test di primalità definito all'interno del file `primo.s`. L'eseguibile viene creato dando il comando `make primi` 13 | 14 | 15 | 5. Se volete utilizzare `gdbgui` come debugger come visto a lezione dovete installarlo con il comando `pip install gdbgui` come descritto sulla [guida ufficiale](https://www.gdbgui.com/). 16 | 17 | 18 | 19 | ### Per chi non ha un Raspberry... 20 | 21 | In questo caso per testare i programmi in assembler dovete usare il procedimento di cross-compilazione indicato nelle dispense di AESO. Nel `makefile` allegato trovate (commentate) le definizioni delle variabili `CC` e `CFLAGS` necessarie per la cross-compilazione sulla macchina `laboratorio2`. Dopo la compilazione per eseguire i programmi dovete precederli da `qemu-arm`, ad esempio `qemu-arm primi 40`. Per il debugging dei programmi in arm su `laboratorio2` dovete usare `gdb-multiarch` (gdbgui non funziona) e non potete usare `valgrind`. 22 | 23 | -------------------------------------------------------------------------------- /07threads/contaprimi.c: -------------------------------------------------------------------------------- 1 | #include "xerrori.h" 2 | 3 | // primo esempio di utilizzo di thread 4 | // conteggio dei primi con thread multipli 5 | 6 | // mostra come usare una struct per condividere dei parametri 7 | // di input e output tra thread principale e ausiliari 8 | 9 | // si tratta della situazione piu semplice in cui il lavoro 10 | // può essere soddiviso in più parti indipendenti; 11 | 12 | 13 | //Prototipo test di primalità 14 | bool primo(int n); 15 | 16 | // struct usata per passare argomenti ai thread 17 | typedef struct { 18 | int start; // intervallo dove cercare i primo 19 | int end; // parametri di input 20 | int somma_parziale; // parametro di output 21 | } dati; 22 | 23 | // funzione passata a pthred_create 24 | void *tbody(void *v) { 25 | dati *d = (dati *) v; 26 | int primi = 0; 27 | fprintf(stderr, "Conto i primi fra %d e %d\n", d->start, d->end); 28 | // cerco i primi nell'intervallo assegnato 29 | for(int j=d->start;jend;j++) { 30 | if(primo(j)) primi++; 31 | } 32 | fprintf(stderr, "Il thread che partiva da %d ha terminato\n", d->start); 33 | d->somma_parziale = primi; 34 | pthread_exit(NULL); 35 | } 36 | 37 | int main(int argc,char *argv[]) 38 | { 39 | if(argc!=3) { 40 | fprintf(stderr,"Uso\n\t%s m num_threads\n", argv[0]); 41 | exit(1); 42 | } 43 | // conversione input 44 | int m= atoi(argv[1]); 45 | if(m<1) termina("limite primi non valido"); 46 | int p= atoi(argv[2]); 47 | if(p<=0) termina("numero di thread non valido"); 48 | 49 | // creazione thread ausiliari 50 | pthread_t t[p]; // array di p indentificatori di thread 51 | dati d[p]; // array di p struct che passerò ai p thread 52 | for(int i=0; i // permette di usare scanf printf etc ... 3 | #include // conversioni stringa/numero exit() etc ... 4 | #include // gestisce tipo bool (per variabili booleane) 5 | #include // permette di usare la funzione assert 6 | #include // funzioni di confronto/copia/etc di stringhe 7 | #include // richiesto per usare errno 8 | 9 | // Scopo del programma: 10 | // mostrare come si crea un file binario 11 | // in questo esempio viene scritto un intero alla volta 12 | // ma se ho un array posso scriverlo con una singola fwrite 13 | 14 | void termina(const char *messaggio); 15 | 16 | 17 | // dato k restituisco true se è primo, false altrimenti 18 | bool primo(int k) 19 | { 20 | assert(k>0); 21 | if(k%2==0) 22 | return k==2; // se k è pari allora è primo se e solo se k==2 23 | 24 | // mi occupo ora del caso k dispari 25 | assert(k%2!=0); 26 | for(int i=3; ik) break; 29 | } 30 | return true; 31 | } 32 | 33 | 34 | int main(int argc, char *argv[]) 35 | { 36 | // verifica siano stati forniti esattamente 2 parametri 37 | if(argc!=3) { 38 | printf("Uso: %s N nome_file\n",argv[0]); 39 | return 1; 40 | } 41 | // converte il primo parametro in un intero 42 | int n = atoi(argv[1]); 43 | if(n<=0) termina("Il parametro n deve essere positivo"); 44 | // copia il puntatore nella variabile nome_file 45 | char *nome_file = argv[2]; 46 | 47 | // apro il file in scrittura 48 | FILE *f = fopen(nome_file,"wb"); 49 | if(f==NULL) termina("Apertura file fallita"); 50 | 51 | // cerca i primi da 2 a n e li scrive dentro il file 52 | for(int i=2;i<=n;i++) 53 | if(primo(i)) { 54 | // scrittura dell'intero i in formato binario 55 | int e = fwrite(&i,sizeof(i),1,f); 56 | if(e!=1) termina("Errore nella scrittura"); 57 | } 58 | // se io avessi messo i primi in un array a[0...k-1], 59 | // li avrei potuti scrivere in f con l'istruzione 60 | // fwrite(a,sizeof(*a),k,f); 61 | 62 | // chiudi il file e termina 63 | if(fclose(f)==EOF) 64 | termina("Errore chiusura file");; 65 | 66 | return 0; 67 | } 68 | 69 | 70 | // stampa su stderr il messaggio che gli passo 71 | // se errno!=0 stampa anche il messaggio d'errore associato 72 | // a errno. dopo queste stampe termina il programma 73 | void termina(const char *messaggio) 74 | { 75 | if(errno==0) 76 | fprintf(stderr,"%s\n",messaggio); 77 | else 78 | perror(messaggio); 79 | exit(1); 80 | } 81 | -------------------------------------------------------------------------------- /03assembler/array_primi.c: -------------------------------------------------------------------------------- 1 | #define _GNU_SOURCE // avverte che usiamo le estensioni GNU 2 | #include // permette di usare scanf printf etc ... 3 | #include // conversioni stringa/numero exit() etc ... 4 | #include // gestisce tipo bool (per variabili booleane) 5 | #include // permette di usare la funzione assert 6 | #include // funzioni di confronto/copia/etc di stringhe 7 | 8 | 9 | // prototipi delle funzioni che appaiono dopo il main() 10 | void stampa_array(int *a, int n); 11 | void termina(char *messaggio); 12 | 13 | 14 | 15 | // funzione che prende in input un intero n e restituisce 16 | // l'array di tutti i primi <=n 17 | // in *num_elementi scrivo quanto elementi ci sono nel'array 18 | // implementata in elenco_primi.s 19 | int *array_primi(int n, int *num_elementi); 20 | 21 | 22 | 23 | // legge un intero N, costruisce array dei primi <=N, e lo stampa 24 | int main(int argc, char *argv[]) 25 | { 26 | int n; 27 | 28 | if(argc!=2) { 29 | printf("Uso: %s nmax\n",argv[0]); 30 | return 1; 31 | } 32 | n = atoi(argv[1]); 33 | 34 | if(n<2) 35 | termina("L'array che ti interesa è vuoto"); 36 | 37 | int *a; // array che conterrà i primi 38 | assert(sizeof(a)==4); // verifichiamo che i puntatori siano 32 bit 39 | int messi; 40 | a = array_primi(n,&messi); 41 | 42 | stampa_array(a,messi); 43 | 44 | // dealloco l'array (da fare solo dopo che ho finito di usarlo!) 45 | free(a); 46 | return 0; 47 | } 48 | 49 | 50 | 51 | // visualizza elementi array di un qualsiasi 52 | // array di int sul terminale 53 | void stampa_array(int *a, int n) 54 | { 55 | // stampo il contenuto dell'array 56 | for(int i=0;i=2); 73 | int *a = malloc(((n+1)/2)*sizeof(int)); 74 | if(a==NULL) termina("out of mem"); 75 | a[0]=2; // inserimo 2 tra i primi 76 | int messi=1; 77 | for(int i=3; i<=n; i+=2) { 78 | if(primo(i)) { 79 | // se l'intero i è primo lo inserisco 80 | a[messi] = i; 81 | messi += 1; 82 | } 83 | } 84 | // tabella completata 85 | assert(messi<(n+1)/2); 86 | // riduco array alla dimensione minima 87 | a = realloc(a,messi*sizeof(int)); 88 | if(a==NULL) termina("Realloc fallita"); 89 | *num=messi; 90 | return a; 91 | } 92 | #endif 93 | -------------------------------------------------------------------------------- /02struct/bitops.c: -------------------------------------------------------------------------------- 1 | #define _GNU_SOURCE // avverte che usiamo le estensioni GNU 2 | #include // permette di usare scanf printf etc ... 3 | #include // conversioni stringa/numero exit() etc ... 4 | #include // gestisce tipo bool (per variabili booleane) 5 | #include // permette di usare la funzione assert 6 | #include // funzioni di confronto/copia/etc di stringhe 7 | #include // richiesto per usare errno 8 | 9 | // Scopo del programma: 10 | // mostrare le operazioni sui bit in C 11 | 12 | static void termina(const char *messaggio); 13 | 14 | 15 | #if 0 16 | && || And e Or logici 17 | 18 | a=2 19 | b=9 20 | a && b -> true 21 | 22 | 23 | ----- 24 | & | ^ bitwise operazioni tra i bit degli interi 25 | 26 | a =00000011 27 | b =00001001 28 | 29 | a&b -> 00000001 30 | a|b -> 00001011 31 | a^b => 00001010 32 | 33 | esiste anche il ~ (not bitwise) 34 | ~a = 11111100 35 | 36 | 37 | << shift sin 38 | >> shift dex 39 | 40 | b = 00001001 41 | 42 | c = b<<3 -> 01001000 43 | c>>2 -> 00010010 44 | 45 | In C lo shift destro può essere aritmetico o logico 46 | il comportamento è implementation dependent 47 | d = 110000....1 48 | d>>2 49 | possiamo ottenere 00110000.... 50 | ma anche 1111000000 51 | e = 001000....1 (il bit più significativo è 0) 52 | e>>2 ottengo sempre 00001000... 53 | #endif 54 | 55 | 56 | // converte il primo intero passato sulla linea di comando in binario 57 | // e il secondo da binario a decimale 58 | int main(int argc, char *argv[]) 59 | { 60 | // verifica siano stati forniti due parametri 61 | if(argc!=3) { 62 | printf("Uso: %s intero stringa01\n",argv[0]); 63 | return 1; 64 | } 65 | int n = atoi(argv[1]); 66 | 67 | for(int i=31;i>=0;i--) { 68 | int mask = 1<31) 78 | termina("Stringa in input troppo lunga"); 79 | for(int i=0;i // permette di usare scanf printf etc ... 3 | #include // conversioni stringa/numero exit() etc ... 4 | #include // gestisce tipo bool (per variabili booleane) 5 | #include // permette di usare la funzione assert 6 | #include // funzioni di confronto/copia/etc di stringhe 7 | #include // richiesto per usare errno 8 | // richesti dalla open 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | // Scopo del programma: 15 | // mostrare come si crea un file binario 16 | // in questo esempio viene scritto un intero alla volta 17 | // ma se ho un array posso scriverlo con una singola fwrite 18 | 19 | void termina(const char *messaggio); 20 | 21 | 22 | // dato k restituisco true se è primo, false altrimenti 23 | bool primo(int k) 24 | { 25 | assert(k>0); 26 | if(k%2==0) 27 | return k==2; // se k è pari allora è primo se e solo se k==2 28 | 29 | // mi occupo ora del caso k dispari 30 | assert(k%2!=0); 31 | for(int i=3; ik) break; 34 | } 35 | return true; 36 | } 37 | 38 | 39 | int main(int argc, char *argv[]) 40 | { 41 | // verifica siano stati forniti esattamente 2 parametri 42 | if(argc!=3) { 43 | printf("Uso: %s N nome_file\n",argv[0]); 44 | return 1; 45 | } 46 | // converte il primo parametro in un intero 47 | int n = atoi(argv[1]); 48 | if(n<=0) termina("Il parametro n deve essere positivo"); 49 | // copia il puntatore nella variabile nome_file 50 | char *nome_file = argv[2]; 51 | 52 | // apro il file in scrittura usando open 53 | // i permessi specificati nell'ultimo argomento 54 | // valgono solo quando il file viene creato! 55 | // i permessi effettivi dipendono anche dalla umask 56 | int fd = open(nome_file,O_WRONLY|O_CREAT,0666); 57 | if(fd<0) termina("Apertura file fallita"); 58 | 59 | // cerca i primi da 2 a n e li scrive dentro il file 60 | for(int i=2;i<=n;i++) 61 | if(primo(i)) { 62 | // scrittura dell'intero i in formato binario con write(2) 63 | int e = write(fd,&i,sizeof(i)); 64 | if(e!=sizeof(int)) termina("Errore nella scrittura"); 65 | } 66 | // se io avessi messo i primi in un array a[0...k-1], 67 | // li avrei potuti scrivere in fd con l'istruzione 68 | // write(fd,a,sizeof(*a)*k); 69 | 70 | // chiudi il file e termina 71 | if(close(fd)<0) 72 | termina("Errore chiusura file");; 73 | return 0; 74 | } 75 | 76 | 77 | // stampa su stderr il messaggio che gli passo 78 | // se errno!=0 stampa anche il messaggio d'errore associato 79 | // a errno. dopo queste stampe termina il programma 80 | void termina(const char *messaggio) 81 | { 82 | if(errno==0) 83 | fprintf(stderr,"%s\n",messaggio); 84 | else 85 | perror(messaggio); 86 | exit(1); 87 | } 88 | -------------------------------------------------------------------------------- /07threads/atcontaprimi.c: -------------------------------------------------------------------------------- 1 | #include "xerrori.h" 2 | #include 3 | 4 | // versione modificata di contaprimi.c 5 | // nella quale viene mostrato l'utilizzo 6 | // di una variabile atomic_int che 7 | // per aggiornare in simultanea la somma dei primi 8 | // contenuta in *(d->somma) 9 | 10 | 11 | // Il codice ha solo interesse didattico: non c'è motivo 12 | // per incrementare continuamente una variabile condivisa 13 | // i singoli thread potrebbero incrementare una variabile private 14 | // e calcolare la somma complessiva solo alla fine 15 | 16 | 17 | //Prototipo test di primalità 18 | bool primo(int n); 19 | 20 | // struct usata per passare argomenti ai thread 21 | typedef struct { 22 | int start; // intervallo dove cercare i primo 23 | int end; // parametri di input 24 | atomic_int *somma; // parametro di output 25 | } dati; 26 | 27 | // funzione passata a pthred_create 28 | void *tbody(void *v) { 29 | dati *d = (dati *) v; 30 | fprintf(stderr, "Conto i primi fra %d e %d\n", d->start, d->end); 31 | // cerco i primi nell'intervallo assegnato 32 | for(int j=d->start;jend;j++) { 33 | if(primo(j)) { 34 | // quando trovo un primo incemento di uno *(d->somma) 35 | atomic_fetch_add(d->somma,1); // incrementa in maniera atomica 36 | // *(d->somma) += 1; // anche questo è atomico ma è meno chiaro 37 | //*(d->somma) = *(d->somma) + 1; // attenzione questo non atomico 38 | } 39 | } 40 | fprintf(stderr, "Il thread che partiva da %d ha terminato\n", d->start); 41 | pthread_exit(NULL); 42 | } 43 | 44 | int main(int argc,char *argv[]) 45 | { 46 | if(argc!=3) { 47 | fprintf(stderr,"Uso\n\t%s m num_threads\n", argv[0]); 48 | exit(1); 49 | } 50 | // conversione input 51 | int m= atoi(argv[1]); 52 | if(m<1) termina("limite primi non valido"); 53 | int p= atoi(argv[2]); 54 | if(p<=0) termina("numero di thread non valido"); 55 | 56 | // creazione thread ausiliari 57 | atomic_int somma = 0; 58 | pthread_t t[p]; // array di p indentificatori di thread 59 | dati d[p]; // array di p struct che passerò ai p thread 60 | for(int i=0; i0, "Il numero di thread deve essere maggiore di 0" 38 | # crea l'intervallo per ognuno dei p thread 39 | somma = Somma() 40 | with concurrent.futures.ThreadPoolExecutor(max_workers=p) as executor: 41 | for i in range(p): 42 | ai = a+(b-a)*i//p 43 | bi = a+(b-a)*(i+1)//p-1 44 | # esempio di uso di submit(): crea un singolo thread 45 | # che esegue la funzione tbody con i parametri ai, bi, somma 46 | executor.submit(tbody, ai, bi, somma) 47 | print(f"La somma dei primi in [{a},{b}) e' {somma.somma}") 48 | logging.debug("Termina esecuzione di main") 49 | return 50 | 51 | 52 | # restituisce lista dei primi in [a,b] 53 | def elenco_primi(a,b): 54 | ris = [] 55 | for i in range(a,b+1): 56 | if primo(i): 57 | ris.append(i); 58 | return ris 59 | 60 | 61 | # dato un intero n>0 restituisce True se n e' primo 62 | # False altrimenti 63 | def primo(n): 64 | assert n>0, "L'input deve essere positivo" 65 | if n==1: 66 | return False 67 | if n==2: 68 | return True 69 | if n%2 == 0: 70 | return False 71 | assert n>=3 and n%2==1, "C'e' qualcosa che non funziona" 72 | for i in range(3,n//2,2): 73 | if n%i==0: 74 | return False 75 | if i*i > n: 76 | break 77 | return True 78 | 79 | 80 | # invoca il main con i parametri passati sulla linea di comando 81 | if len(sys.argv)==3: 82 | main(int(sys.argv[1]), int(sys.argv[2]), 1) 83 | elif len(sys.argv)==4: 84 | main(int(sys.argv[1]), int(sys.argv[2]), int(sys.argv[3])) 85 | else: 86 | print("Uso:\n\t %s inizio fine [numthread]" % sys.argv[0]) 87 | 88 | 89 | 90 | -------------------------------------------------------------------------------- /08condVar/heap.c: -------------------------------------------------------------------------------- 1 | #include "xerrori.h" 2 | // abbreviamo la chiamata alle funzioni x... 3 | #define QUI __LINE__,__FILE__ 4 | 5 | 6 | // gestione di heap mediante condition variable 7 | // per fare si che le stampe riflettano l'effettivo ordine 8 | // delle operazioni queste sono effettuate quando il 9 | // mutex è sempre bloccato 10 | 11 | // struct che tiene traccia della memoria disponibile e 12 | // contiene le variabili cond/mutex per regolarne l'utilizzo 13 | typedef struct { 14 | pthread_cond_t *cv; // condition variable 15 | pthread_mutex_t *mu; // mutex 16 | int MB; // memoria attualmente disponibile 17 | } heap; 18 | 19 | // simula allocazione con spazio limitato 20 | void richiedi(heap *h, int n) { 21 | xpthread_mutex_lock(h->mu,QUI); 22 | fprintf(stderr,"%2d Richiesti: %3d\n", gettid()%100, n); 23 | while(n>h->MB) { 24 | fprintf(stderr,"%2d Negati: %3d\n", gettid()%100, n); 25 | xpthread_cond_wait(h->cv,h->mu,QUI); 26 | } 27 | h->MB -= n; 28 | fprintf(stderr,"%2d Assegnati: %3d. Rimanenti: %4d\n\n", gettid()%100, 29 | n,h->MB); 30 | xpthread_mutex_unlock(h->mu,QUI); 31 | } 32 | 33 | // deallocazione 34 | void libera(heap *h, int n) { 35 | xpthread_mutex_lock(h->mu,QUI); 36 | h->MB += n; 37 | xpthread_cond_broadcast(h->cv,QUI); 38 | fprintf(stderr,"%2d Restituiti: %3d. Rimanenti: %4d\n\n", gettid()%100, 39 | n,h->MB); 40 | xpthread_mutex_unlock(h->mu,QUI); 41 | } 42 | 43 | 44 | // codice thread tipo 1, chiede 10,20,...,50 45 | void *tipo1(void *v) { 46 | heap *h = (heap *) v; 47 | for(int i=1;i<=5;i++) { 48 | int m = 10*i; 49 | richiedi(h,m); 50 | sleep(1); 51 | libera(h,m); 52 | } 53 | return NULL; 54 | } 55 | 56 | // codice thread tipo 2, chiede 15,25,...,55 57 | void *tipo2(void *v) { 58 | heap *h = (heap *) v; 59 | for(int i=1;i<=5;i++) { 60 | int m = 10*i+5; 61 | richiedi(h,m); 62 | sleep(1); 63 | libera(h,m); 64 | } 65 | return NULL; 66 | } 67 | 68 | 69 | int main(int argc, char *argv[]) 70 | { 71 | // controlla numero argomenti 72 | if(argc!=3) { 73 | printf("Uso: %s mem numT\n",argv[0]); 74 | return 1; 75 | } 76 | int mem = atoi(argv[1]); 77 | int nt = atoi(argv[2]); 78 | assert(nt>1); 79 | 80 | // inizializza heap 81 | pthread_cond_t c = PTHREAD_COND_INITIALIZER; 82 | pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER; 83 | heap h; 84 | h.cv = &c; h.mu = &m; 85 | h.MB = mem; 86 | 87 | // esegue i thread 88 | pthread_t t[nt]; 89 | // esegue un thread tipo1 90 | xpthread_create(&t[0],NULL,&tipo1,&h,QUI); 91 | for(int i=1;i // permette di usare scanf printf etc ... 5 | #include // conversioni stringa/numero rand() abs() exit() etc ... 6 | #include // gestisce tipo bool (per variabili booleane) 7 | #include // permette di usare la funzione assert 8 | #include // richiesto per usare errno 9 | 10 | // stampa un messaggio di errore e termina 11 | void termina(const char *messaggio); 12 | 13 | 14 | // funzione di confronto, con i tipi corretti 15 | // necessita del casting al tipo __compar_fn_t 16 | // nella chiamata del qsort altrimenti il compilatore 17 | // da un warning 18 | int confronta(int *a, int *b) 19 | { 20 | if(*a<*b) return -1; 21 | else if(*a>*b) return 1; 22 | return 0; 23 | } 24 | 25 | // funzione di confronto che ordina mettendo prima tutti i pari 26 | // e successivamente tutti i dispari 27 | int confrontapd(int *a, int *b) 28 | { 29 | // i pari prima dei dispari 30 | if(*a%2==0 && *b%2!=0) return -1; 31 | if(*a%2!=0 && *b%2==0) return 1; 32 | // ora dovrebbero esere entrambi pari o entrambi dispari 33 | assert( (*a%2==0 && *b%2==0) || 34 | (*a%2!=0 && *b%2!=0)); 35 | // ordinamento in ordine crescente 36 | if(*a<*b) return -1; 37 | else if(*a>*b) return 1; 38 | return 0; 39 | } 40 | 41 | 42 | int main(int argc, char *argv[]) 43 | { 44 | if(argc<=2) { // input sulla linea di comando non corretto 45 | printf("Uso: %s i1 i2 i3 ... ik \n",argv[0]); 46 | return 1; 47 | } 48 | int n = argc-1; // Numero argomenti linea di comando 49 | 50 | // alloco array dinamico 51 | int *a = malloc(n*sizeof(int)); 52 | if(a==NULL) termina("Memoria insufficiente"); 53 | // riempio con interi passati sulla linea di comando 54 | for(int i=0;i // permette di usare scanf printf etc ... 3 | #include // conversioni stringa exit() etc ... 4 | #include // gestisce tipo bool 5 | #include // permette di usare la funzione ass 6 | #include // funzioni per stringhe 7 | #include // richiesto per usare errno 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include /* For mode constants */ 16 | #include /* For O_* constants */ 17 | #include 18 | 19 | // termina programma 20 | void termina(const char *s); 21 | void xtermina(const char *s, int linea, char *file); 22 | 23 | // operazioni su FILE * 24 | FILE *xfopen(const char *path, const char *mode, int linea, char *file); 25 | 26 | // operazioni su file descriptors 27 | void xclose(int fd, int linea, char *file); 28 | 29 | // thread 30 | void xperror(int en, char *msg); 31 | 32 | int xpthread_create(pthread_t *thread, const pthread_attr_t *attr, 33 | void *(*start_routine) (void *), void *arg, int linea, char *file); 34 | int xpthread_join(pthread_t thread, void **retval, int linea, char *file); 35 | 36 | // mutex 37 | int xpthread_mutex_init(pthread_mutex_t *restrict mutex, const pthread_mutexattr_t *restrict attr, int linea, char *file); 38 | int xpthread_mutex_destroy(pthread_mutex_t *mutex, int linea, char *file); 39 | int xpthread_mutex_lock(pthread_mutex_t *mutex, int linea, char *file); 40 | int xpthread_mutex_unlock(pthread_mutex_t *mutex, int linea, char *file); 41 | 42 | // barrier 43 | int xpthread_barrier_init(pthread_barrier_t *restrict barrier, const pthread_barrierattr_t *restrict attr, 44 | unsigned int count, int linea, char *file); 45 | int xpthread_barrier_destroy(pthread_barrier_t *barrier, int linea, char *file); 46 | int xpthread_barrier_wait(pthread_barrier_t *barrier, int linea, char *file); 47 | 48 | // semafori named e unnamed POSIX 49 | sem_t *xsem_open(const char *name, int oflag, mode_t mode, unsigned int value, int linea, char *file); 50 | int xsem_unlink(const char *name, int linea, char *file); 51 | int xsem_close(sem_t *sem, int linea, char *file); 52 | int xsem_init(sem_t *sem, int pshared, unsigned int value, int linea, char *file); 53 | int xsem_destroy(sem_t *sem, int linea, char *file); 54 | int xsem_post(sem_t *sem, int linea, char *file); 55 | int xsem_wait(sem_t *sem, int linea, char *file); 56 | 57 | // condition variables 58 | int xpthread_cond_init(pthread_cond_t *restrict cond, const pthread_condattr_t *restrict attr, int linea, char *file); 59 | int xpthread_cond_destroy(pthread_cond_t *cond, int linea, char *file); 60 | int xpthread_cond_wait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex, int linea, char *file); 61 | int xpthread_cond_signal(pthread_cond_t *cond, int linea, char *file); 62 | int xpthread_cond_broadcast(pthread_cond_t *cond, int linea, char *file); 63 | 64 | -------------------------------------------------------------------------------- /08condVar/xerrori.h: -------------------------------------------------------------------------------- 1 | #define _GNU_SOURCE // permette di usare estensioni GNU 2 | #include // permette di usare scanf printf etc ... 3 | #include // conversioni stringa exit() etc ... 4 | #include // gestisce tipo bool 5 | #include // permette di usare la funzione ass 6 | #include // funzioni per stringhe 7 | #include // richiesto per usare errno 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include /* For mode constants */ 16 | #include /* For O_* constants */ 17 | #include 18 | 19 | // termina programma 20 | void termina(const char *s); 21 | void xtermina(const char *s, int linea, char *file); 22 | 23 | // operazioni su FILE * 24 | FILE *xfopen(const char *path, const char *mode, int linea, char *file); 25 | 26 | // operazioni su file descriptors 27 | void xclose(int fd, int linea, char *file); 28 | 29 | // thread 30 | void xperror(int en, char *msg); 31 | 32 | int xpthread_create(pthread_t *thread, const pthread_attr_t *attr, 33 | void *(*start_routine) (void *), void *arg, int linea, char *file); 34 | int xpthread_join(pthread_t thread, void **retval, int linea, char *file); 35 | 36 | // mutex 37 | int xpthread_mutex_init(pthread_mutex_t *restrict mutex, const pthread_mutexattr_t *restrict attr, int linea, char *file); 38 | int xpthread_mutex_destroy(pthread_mutex_t *mutex, int linea, char *file); 39 | int xpthread_mutex_lock(pthread_mutex_t *mutex, int linea, char *file); 40 | int xpthread_mutex_unlock(pthread_mutex_t *mutex, int linea, char *file); 41 | 42 | // barrier 43 | int xpthread_barrier_init(pthread_barrier_t *restrict barrier, const pthread_barrierattr_t *restrict attr, 44 | unsigned int count, int linea, char *file); 45 | int xpthread_barrier_destroy(pthread_barrier_t *barrier, int linea, char *file); 46 | int xpthread_barrier_wait(pthread_barrier_t *barrier, int linea, char *file); 47 | 48 | // semafori named e unnamed POSIX 49 | sem_t *xsem_open(const char *name, int oflag, mode_t mode, unsigned int value, int linea, char *file); 50 | int xsem_unlink(const char *name, int linea, char *file); 51 | int xsem_close(sem_t *sem, int linea, char *file); 52 | int xsem_init(sem_t *sem, int pshared, unsigned int value, int linea, char *file); 53 | int xsem_destroy(sem_t *sem, int linea, char *file); 54 | int xsem_post(sem_t *sem, int linea, char *file); 55 | int xsem_wait(sem_t *sem, int linea, char *file); 56 | 57 | // condition variables 58 | int xpthread_cond_init(pthread_cond_t *restrict cond, const pthread_condattr_t *restrict attr, int linea, char *file); 59 | int xpthread_cond_destroy(pthread_cond_t *cond, int linea, char *file); 60 | int xpthread_cond_wait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex, int linea, char *file); 61 | int xpthread_cond_signal(pthread_cond_t *cond, int linea, char *file); 62 | int xpthread_cond_broadcast(pthread_cond_t *cond, int linea, char *file); 63 | 64 | -------------------------------------------------------------------------------- /11pythreads/rw.py: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env python3 2 | import threading 3 | import time 4 | 5 | class RW: 6 | def __init__(self): 7 | self.readers = 0 8 | self.writing = False 9 | self.wpending = 0 10 | self.cond = threading.Condition() 11 | 12 | # Reader lock 13 | def read_lock(self): 14 | tid = threading.get_native_id() % 100 15 | print(f"{tid:2d} read request") 16 | with self.cond: 17 | while self.writing or self.wpending > 0: 18 | self.cond.wait() 19 | self.readers += 1 20 | 21 | # Reader unlock 22 | def read_unlock(self): 23 | tid = threading.get_native_id() % 100 24 | print(f"{tid:2d} read completed") 25 | with self.cond: 26 | assert self.readers > 0 # There must be at least one reader 27 | assert not self.writing # There must not be any writer 28 | self.readers -= 1 29 | if self.readers == 0: 30 | self.cond.notify() 31 | 32 | # Writer lock 33 | def write_lock(self): 34 | tid = threading.get_native_id() % 100 35 | print(f"{tid:2d} write request") 36 | with self.cond: 37 | self.wpending += 1 38 | while self.writing or self.readers > 0: 39 | self.cond.wait() 40 | self.writing = True 41 | self.wpending -= 1 42 | 43 | # Writer unlock 44 | def write_unlock(self): 45 | tid = threading.get_native_id() % 100 46 | print(f"{tid:2d} write completed") 47 | with self.cond: 48 | assert self.writing 49 | self.writing = False 50 | self.cond.notify_all() 51 | 52 | # Reader thread function 53 | def lettore(rw_obj): 54 | rw_obj.read_lock() 55 | time.sleep(1) 56 | rw_obj.read_unlock() 57 | 58 | # Writer thread function 59 | def scrittore(rw_obj): 60 | rw_obj.write_lock() 61 | time.sleep(1) 62 | rw_obj.write_unlock() 63 | 64 | def main(): 65 | rw_obj = RW() 66 | threads = [] 67 | 68 | # Create threads 69 | threads.append(threading.Thread(target=lettore, args=(rw_obj,))) 70 | threads.append(threading.Thread(target=lettore, args=(rw_obj,))) 71 | threads.append(threading.Thread(target=scrittore, args=(rw_obj,))) 72 | threads.append(threading.Thread(target=lettore, args=(rw_obj,))) 73 | threads.append(threading.Thread(target=lettore, args=(rw_obj,))) 74 | threads.append(threading.Thread(target=lettore, args=(rw_obj,))) 75 | threads.append(threading.Thread(target=lettore, args=(rw_obj,))) 76 | threads.append(threading.Thread(target=lettore, args=(rw_obj,))) 77 | threads.append(threading.Thread(target=lettore, args=(rw_obj,))) 78 | threads.append(threading.Thread(target=scrittore, args=(rw_obj,))) 79 | threads.append(threading.Thread(target=lettore, args=(rw_obj,))) 80 | threads.append(threading.Thread(target=lettore, args=(rw_obj,))) 81 | threads.append(threading.Thread(target=lettore, args=(rw_obj,))) 82 | threads.append(threading.Thread(target=lettore, args=(rw_obj,))) 83 | 84 | # Start threads 85 | for t in threads: 86 | t.start() 87 | 88 | # Wait for all threads to finish 89 | for t in threads: 90 | t.join() 91 | 92 | # Final assertions 93 | assert rw_obj.wpending == 0 94 | assert not rw_obj.writing 95 | assert rw_obj.readers == 0 96 | 97 | if __name__ == "__main__": 98 | main() 99 | -------------------------------------------------------------------------------- /01introC/leggi_interi.c: -------------------------------------------------------------------------------- 1 | #define _GNU_SOURCE // avverte che usiamo le estensioni GNU 2 | #include // permette di usare scanf printf etc ... 3 | #include // conversioni stringa/numero exit() etc ... 4 | #include // gestisce tipo bool (per variabili booleane) 5 | #include // permette di usare la funzione assert 6 | #include // funzioni di confronto/copia/etc di stringhe 7 | #include // necessaria per usare errno 8 | 9 | // Scopo del programma: 10 | // mostrare come si legge da un file di testo 11 | // e come una funzione può restituire un array 12 | // alla funzione chiamante 13 | 14 | // prototipo della funzione termina() 15 | void termina(char *messaggio); 16 | 17 | 18 | // legge gli interi che sono nel file f 19 | // e li salva in un array che viene restituito 20 | // con return + passaggio per riferimento 21 | int *leggi_file(FILE *f, int *num_elementi) 22 | { 23 | assert(f!=NULL); // il file deve essere valido 24 | int size=10; // dimensione attuale dell'array 25 | int messi=0; // numero di elementi attualmente nell'array 26 | int *a = malloc(size*sizeof(int)); 27 | if(a==NULL) 28 | termina("Memoria insufficiente"); 29 | 30 | while(true) { 31 | int n; 32 | int e = fscanf(f,"%d",&n); 33 | if(e==EOF) break; 34 | if(e!=1) termina("Contenuto illegale nel file"); 35 | // ho letto un intero dal file ed è stato messo in n 36 | if(messi==size) { 37 | // ingrandisco l'array 38 | size = size*2; 39 | a = realloc(a,size*sizeof(int)); 40 | if(a==NULL) 41 | termina("realloc fallita"); 42 | } 43 | assert(size>messi); 44 | a[messi] = n; 45 | messi += 1; 46 | } 47 | // ho messo tutti gli elementi che mi interessavano 48 | size = messi; 49 | a = realloc(a,size*sizeof(int)); 50 | if(a==NULL) 51 | termina("realloc fallita"); 52 | // salvo il numero di elementi e restituisco l'array 53 | *num_elementi = messi; 54 | return a; 55 | } 56 | 57 | // visualizza elementi di un array di int su stdout 58 | // stampa "Ho finito!" su stderr 59 | // Nota: fprintf(stdout,... è equivalente a printf(....) 60 | void stampa_array(int *a, int n) 61 | { 62 | assert(a!=NULL); 63 | assert(n>=0); 64 | // stampo il contenuto dell'array 65 | for(int i=0;i // permette di usare scanf printf etc ... 3 | #include // conversioni stringa exit() etc ... 4 | #include // gestisce tipo bool 5 | #include // permette di usare la funzione assert 6 | #include // funzioni per stringhe 7 | #include // richiesto per usare errno 8 | 9 | /** 10 | Esercizio: 11 | 12 | Scrivere un programma che legge dalla riga 13 | di comando un elenco di file e stampa 14 | questi file ordinati per dimensione decrescente, 15 | i file con la stessa dimensione devono essere 16 | ordinati lessicograficamente. 17 | 18 | Esercizio svolto tranne parte sull'ordinamento 19 | 20 | **/ 21 | 22 | 23 | // prototipi delle funzioni che appaiono dopo il main() 24 | void termina(const char *messaggio); 25 | 26 | 27 | // definizione struct che rappresenta 28 | // una file con nome e lunghezza 29 | typedef struct { 30 | char *nome; 31 | long lung; 32 | } miofile; 33 | 34 | // crea oggetto capitale a partire dai suoi campi 35 | miofile *miofile_crea(char *s) 36 | { 37 | assert(s!=NULL); 38 | // apro file in lettura 39 | FILE *f = fopen(s,"r"); 40 | if(f==NULL) { 41 | fprintf(stderr,"Non è stato possibile aprire il file %s\n",s); 42 | return NULL; 43 | } 44 | if(fseek(f,0,SEEK_END)!=0) { 45 | fprintf(stderr,"Non è stato possibile fare seek sul file %s\n",s); 46 | fclose(f); 47 | return NULL; 48 | } 49 | // ora il puntatore è alla fine del file 50 | long pos = ftell(f); 51 | if(pos<0) { 52 | fprintf(stderr,"Non è stato possibile fare ftell sul file %s\n",s); 53 | fclose(f); 54 | return NULL; 55 | } 56 | fclose(f); 57 | // se siamo arrivati qui pos contiene 58 | // la lunghezza del file in byte 59 | miofile *a = malloc(sizeof(*a)); 60 | if(a==NULL) termina("Memoria insufficiente"); 61 | a->nome = strdup(s); 62 | a->lung = pos; 63 | return a; 64 | } 65 | 66 | 67 | // distrugge (dealloca) un oggetto capitale 68 | void miofile_distruggi(miofile *a) 69 | { 70 | free(a->nome); 71 | free(a); 72 | } 73 | 74 | // stampa sul file *f i campi del file *a 75 | void miofile_stampa(const miofile *a, FILE *f) { 76 | fprintf(f,"%20ld %s\n",a->lung,a->nome); 77 | } 78 | 79 | 80 | int main(int argc, char *argv[]) 81 | { 82 | if(argc<2) { 83 | printf("Uso: %s nome1 [nome2 nome3 ...]\n",argv[0]); 84 | exit(1); 85 | } 86 | miofile **arr; 87 | arr = malloc((argc-1)*sizeof(*arr)); 88 | if(arr==NULL) termina("Memoria esaurita"); 89 | int n=0; // numero di elementi in arr[] 90 | for(int i=1;i // permette di usare scanf printf etc ... 6 | #include // conversioni stringa/numero rand() abs() exit() 7 | #include // gestisce tipo bool (per variabili booleane) 8 | #include // permette di usare la funzione assert 9 | #include // prototipi delle funzioni per stringhe 10 | 11 | // prototipi 12 | void termina(const char *messaggio); 13 | void stampa_matrice(int r, int c, int q[][c], FILE *f); 14 | void stampa_matrice_dinamica(int r, int c, int **q, FILE *f); 15 | int **crea_matrice_interi(int r, int c); 16 | 17 | 18 | int main(int argc, char *argv[]) 19 | { 20 | if(argc!=3) { 21 | fprintf(stderr,"Uso: %s righe colonne\n",argv[0]); 22 | exit(EXIT_FAILURE); 23 | } 24 | // legge il numero di righe e colonne dalla riga di comando 25 | int righe = atoi(argv[1]); 26 | int colonne = atoi(argv[2]); 27 | if(righe<1 || colonne <1) 28 | termina("Righe e colonne devono essere positive"); 29 | 30 | // matrice allocata staticamente 31 | int a[righe][colonne]; 32 | 33 | for(int i=0;i archi; 19 | // nodi rappresentati come insiemi di archi uscenti 20 | // ordinati per peso crescente 21 | private Map> nodi; 22 | 23 | /** costruttore: inizializza insiemi di archi e nodi 24 | * inizialmente vuoti 25 | * */ 26 | public LogGrafo() { 27 | nodi = new HashMap>(); 28 | archi = new TreeSet(); 29 | } 30 | 31 | public int num_nodi() { 32 | return nodi.size(); 33 | } 34 | 35 | public int num_archi() { 36 | return archi.size(); 37 | } 38 | 39 | // verifica se il grafo contiene un nodo 40 | public boolean contiene_nodo(Nodo n) { 41 | return nodi.containsKey(n); 42 | } 43 | 44 | // aggiunge nodo al grafo 45 | public void aggiungi_nodo(Nodo n) { 46 | if(nodi.containsKey(n)) 47 | throw new IllegalArgumentException("Nodo duplicato"); 48 | nodi.put(n,new TreeSet()); 49 | } 50 | 51 | public void aggiungi_arco(Arco a) { 52 | if(!nodi.containsKey(a.n1)) 53 | throw new IllegalArgumentException("Primo estremo mancante"); 54 | if(!nodi.containsKey(a.n2)) 55 | throw new IllegalArgumentException("Secondo estremo mancante"); 56 | for(Arco x : archi) { 57 | if(a.stessi_estremi(x)) 58 | throw new IllegalArgumentException("Arco duplicato"); 59 | } 60 | // aggiunge arco a uscente da n1 e n2 61 | nodi.get(a.n1).add(a); 62 | nodi.get(a.n2).add(a); 63 | archi.add(a); 64 | } 65 | 66 | // restituisce insieme di archi uscenti da un nodo 67 | // ordinati per peso crescente 68 | public SortedSet uscenti(Nodo n) { 69 | if(!nodi.containsKey(n)) 70 | throw new IllegalArgumentException("Nodo sconosciuto"); 71 | return nodi.get(n); 72 | } 73 | 74 | // restituisce insieme di tutti gli archi del grafo 75 | // ordinati per peso crescente 76 | public SortedSet archi() { 77 | return this.archi; 78 | } 79 | 80 | 81 | /** 82 | * metodo main per testare la classe 83 | * utilizzando nodi di tipo stringa 84 | * 85 | * @param args non usato 86 | */ 87 | public static void main(String[] args) { 88 | // classe di prova per testare il grafo 89 | class Stringa implements Nodo { 90 | String nome; 91 | Stringa(String nome) {this.nome = nome;} 92 | public String etichetta() {return nome;} 93 | } 94 | 95 | // costruisco un grafo con 4 nodi e 4 archi 96 | // i cui nodi sono oggetti di tipo stringa 97 | LogGrafo g = new LogGrafo(); 98 | Stringa a = new Stringa("a"); 99 | Stringa b = new Stringa("b"); 100 | Stringa c = new Stringa("c"); 101 | Stringa d = new Stringa("d"); 102 | g.aggiungi_nodo(a); 103 | g.aggiungi_nodo(b); 104 | g.aggiungi_nodo(c); 105 | g.aggiungi_nodo(d); 106 | g.aggiungi_arco(new Arco(a,b,1.0)); 107 | g.aggiungi_arco(new Arco(a,c,3.0)); 108 | g.aggiungi_arco(new Arco(b,c,1.0)); 109 | g.aggiungi_arco(new Arco(c,d,1.0)); 110 | // calcolo i cammini minimi da a 111 | Map m = g.dijkstra(a); 112 | for(Nodo n : m.keySet()) { 113 | System.out.println(n.etichetta() + " " + m.get(n)); 114 | } 115 | } 116 | 117 | } 118 | 119 | -------------------------------------------------------------------------------- /01introC/stringhe.c: -------------------------------------------------------------------------------- 1 | #define _GNU_SOURCE // avverte che usiamo le estensioni GNU 2 | #include // permette di usare scanf printf etc ... 3 | #include // conversioni stringa/numero exit() etc ... 4 | #include // gestisce tipo bool (per variabili booleane) 5 | #include // permette di usare la funzione assert 6 | #include // funzioni di confronto/copia/etc di stringhe 7 | 8 | 9 | // Scopo del programma: 10 | // mostrare alcuni esempi di funzioni che prendono 11 | // come input stringhe (cioè array di char) 12 | 13 | // stampa un messaggio d'errore e termina il programma 14 | void termina(char *messaggio); 15 | 16 | 17 | // restituisce la lunghezza di una stringa 18 | // equivalente alla funzione di libreria strlen() 19 | // la keyword const indica che i caratteri di s[] sono 20 | // read only: il compilatore segnala errore se li cambiamo 21 | // ad esempio se scriviamo s[0] = 'x' 22 | int str_lunghezza(const char *s) 23 | { 24 | assert(s!=NULL); 25 | int i=0; 26 | while(s[i]!=0) { 27 | i = i+1; 28 | } 29 | assert(s[i]==0); 30 | return i; 31 | } 32 | 33 | // funzione per costruire la concatenazione di due stringhe 34 | // uso apposta i due diversi formati con [] e * perché 35 | // sono equivalenti. Attenzione il formato [] può essere usato 36 | // solo nei prototipi, non nel corpo della funzione 37 | char *str_concatena(char s1[], char *s2) 38 | { 39 | // richiediamo che s1 e s2 non siano null 40 | assert(s1!=NULL); 41 | assert(s2!=NULL); 42 | 43 | // calcolo lunghezza stringa concatenata ricordandomi lo 0 44 | int nuovalun = 1 + str_lunghezza(s1) + str_lunghezza(s2); 45 | 46 | // array dinamico di nuovalun caratteri 47 | char *s3 = malloc(nuovalun*sizeof(char)); 48 | if(s3==NULL) termina("memoria insufficiente"); 49 | 50 | // array statico con lo stesso numero di caratteri 51 | // non va usato!!!! il compilatore correttamente 52 | // segnala che è un errore restituirlo con return 53 | // char s3[nuovalun]; 54 | 55 | int i=0; // indice dentro s3 56 | for(int j=0;s1[j]!=0;j++) { // copio s1 in s3 57 | s3[i] = s1[j]; 58 | i++; 59 | } 60 | for(int j=0;s2[j]!=0;j++) { // copio s2 in s3 61 | s3[i++] = s2[j]; // ho messo incremento di i dentro assegnamento 62 | } 63 | // scrivo terminatore per la stringa s3 64 | s3[i] = 0; // oppure che è lo stesso s3[i]='\0' 65 | 66 | // verifico le lunghezze: uso strlen() della libreria C 67 | assert(strlen(s3)==strlen(s1)+strlen(s2)); 68 | // verifico che corrispondano anche i caratteri allocati 69 | assert(nuovalun == strlen(s3)+1); 70 | // restituisco la stringa contenente la concatenazione 71 | // (cioè il puntatore al primo elemento) 72 | return s3; 73 | } 74 | 75 | 76 | 77 | int main(int argc, char *argv[]) 78 | { 79 | // verifica siano stati forniti 2 parametri 80 | if(argc!=3) { 81 | printf("Uso: %s stringa1 string2\n",argv[0]); 82 | return 1; 83 | } 84 | 85 | // esempi di funzioni per lunghezza e concatenazione di stringhe 86 | int l1 = str_lunghezza(argv[1]); 87 | printf("lunghezza <%s> = %d\n",argv[1],l1); 88 | 89 | char *z = str_concatena(argv[1],argv[2]); 90 | printf("Concatenazione: %s\n",z); 91 | 92 | // dealloca concatenazione 93 | free(z); 94 | 95 | // Nota: gli argv[i] non vanno dellocati perchè non sono 96 | // stati creati con malloc() 97 | return 0; 98 | } 99 | 100 | 101 | // stampa un messaggio d'errore e termina il programma 102 | void termina(char *messaggio) 103 | { 104 | perror(messaggio); 105 | exit(1); 106 | } 107 | 108 | 109 | -------------------------------------------------------------------------------- /01introC/scrivi_primi.c: -------------------------------------------------------------------------------- 1 | #define _GNU_SOURCE // avverte che usiamo le estensioni GNU 2 | #include // permette di usare scanf printf etc ... 3 | #include // conversioni stringa/numero exit() etc ... 4 | #include // gestisce tipo bool (per variabili booleane) 5 | #include // permette di usare la funzione assert 6 | #include // funzioni di confronto/copia/etc di stringhe 7 | 8 | 9 | // da compilare con: 10 | // gcc -std=c11 -Wall -O -g -o scrivi_primi scrivi_primi.c 11 | // oppure, avendo il makefile visto a lezione 12 | // make scrivi_primi 13 | 14 | 15 | // Scopo del programma: 16 | // converte argv[1] nell'intero N 17 | // crea un array *dinamico* con i primi <=N 18 | // salva l'elenco dei primi nel file di nome argv[2] 19 | 20 | 21 | // prototipo della funzione termina() 22 | // il corpo della funzione può apparire dopo il main() 23 | void termina(char *messaggio); 24 | 25 | 26 | // dato k restituisco True se è primo, false altrimenti 27 | // suggerito da copilot (non è bellissimo ma è corretto) 28 | bool primo(int k) { 29 | // se k è pari e diverso da 2 allora non è primo 30 | if(k%2==0 && k!=2) return false; 31 | // se k è dispari e non è primo 32 | // allora esiste un divisore <= sqrt(k) che è dispari 33 | // quindi posso controllare solo i divisori dispari 34 | // e posso fermarmi a sqrt(k) 35 | for(int i=3; i*i<=k; i+=2) { 36 | if(k%i==0) return false; 37 | } 38 | return true; 39 | } 40 | 41 | 42 | int main(int argc, char *argv[]) 43 | { 44 | int n; // definisco variabile intera di nome n 45 | 46 | if(argc!=3) { 47 | printf("Uso: %s intero_pos nome_file\n",argv[0]); 48 | return 1; 49 | } 50 | n = atoi(argv[1]); // converto argv[1] in intero 51 | if(n<1) 52 | termina("E' richiesto un intero *positivo*!"); 53 | 54 | // crea un array dinamico inizialmente di 10 elementi 55 | int *a; // dichiaro che a sarà usata come array 56 | int capacita = 10; // dimensione attuale dell'array 57 | int messi = 0; // numero di elementi attualmente dentro l'array 58 | a = malloc(capacita*sizeof(int)); 59 | if(a==NULL) 60 | termina("Malloc fallita"); 61 | 62 | // riempio array 63 | for(int i=2; i<=n; i++) { 64 | if(primo(i)) { 65 | // se l'intero i è primo lo inserisco 66 | // nella tabella dei primi 67 | // ma prima verifico che ci sia spazio 68 | if(messi==capacita) { 69 | capacita = 2*capacita; // se la tabella è piena raddoppio la dimensione 70 | a = realloc(a,capacita*sizeof(int)); 71 | if(a==NULL) 72 | termina("Realloc fallita"); 73 | } 74 | // inserisco il primo i dentro a[] 75 | a[messi] = i; 76 | messi += 1; 77 | } 78 | } 79 | // tabella completata 80 | // riduco array alla dimensione minima 81 | capacita = messi; 82 | a = realloc(a,capacita*sizeof(int)); 83 | if(a==NULL) termina("Realloc fallita"); 84 | 85 | // apriamo il file per scriveci gli interi 86 | FILE *f = fopen(argv[2],"at"); 87 | if(f==NULL) 88 | termina("Apertura del file fallita"); 89 | 90 | // scrivi su f il contenuto array, un intero per riga 91 | for(int i=0;i elenco = new ArrayList(); 32 | try { 33 | BufferedReader br = new BufferedReader(new FileReader(args[0])); 34 | String linea; 35 | while((linea = br.readLine()) != null) { 36 | // salta linee vuote o commenti 37 | if(linea.length() == 0 || linea.charAt(0) == '#') 38 | continue; 39 | Citta c = new Citta(linea); 40 | if(elenco.contains(c)) 41 | System.out.println("Città duplicata: " + c); 42 | else 43 | elenco.add(c); 44 | } 45 | br.close(); // chiudo il file 46 | } 47 | catch(Exception e) { 48 | System.err.println("Errore: " + e); 49 | e.printStackTrace(); 50 | System.exit(2); 51 | } 52 | // inserisce le citta nel grafo come nodi 53 | LogGrafo g = new LogGrafo(); 54 | for(Citta c: elenco) 55 | g.aggiungi_nodo(c); 56 | // inserisce gli archi nel grafo 57 | // considero tutte le coppie di città distinte 58 | // e inserico un arco se la distanza è minore del limite 59 | double limite = Double.parseDouble(args[1]); 60 | for(int i=0; i m = g.dijkstra(sorgente); 72 | for(Nodo n : m.keySet()) { 73 | System.out.println(n.etichetta() + " " + m.get(n)); 74 | } 75 | System.out.println("Ci sono " + m.size() + " città raggiungibili da " + sorgente.etichetta() ); 76 | } 77 | 78 | /** 79 | * Calcola la distanza fra due città 80 | * 81 | * @param c1 prima città 82 | * @param c2 seconda città 83 | * @return distanza in chilometri 84 | * 85 | Per il calcolo viene utilizzata la formula di Haversine 86 | https://en.wikipedia.org/wiki/Haversine_formula */ 87 | public static double distanza(Citta c1, Citta c2) { 88 | double lat1 = Math.toRadians(c1.lat); 89 | double lat2 = Math.toRadians(c2.lat); 90 | double lon1 = Math.toRadians(c1.lon); 91 | double lon2 = Math.toRadians(c2.lon); 92 | double dlat = lat2 - lat1; 93 | double dlon = lon2 - lon1; 94 | double a = Math.pow(Math.sin(dlat/2),2) + Math.cos(lat1)*Math.cos(lat2)*Math.pow(Math.sin(dlon/2),2); 95 | double c = 2*Math.atan2(Math.sqrt(a),Math.sqrt(1-a)); 96 | return 6371*c; 97 | } 98 | 99 | } 100 | 101 | 102 | -------------------------------------------------------------------------------- /09processi/xerrori.h: -------------------------------------------------------------------------------- 1 | #define _GNU_SOURCE // permette di usare estensioni GNU 2 | #include // permette di usare scanf printf etc ... 3 | #include // conversioni stringa exit() etc ... 4 | #include // gestisce tipo bool 5 | #include // permette di usare la funzione ass 6 | #include // funzioni per stringhe 7 | #include // richiesto per usare errno 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include /* For mode constants */ 16 | #include /* For O_* constants */ 17 | #include 18 | 19 | // termina programma 20 | void termina(const char *s); 21 | void xtermina(const char *s, int linea, char *file); 22 | 23 | // invia messaggio d'errore su stderr 24 | void xperror(int en, char *msg); 25 | 26 | // operazioni su FILE * 27 | FILE *xfopen(const char *path, const char *mode, int linea, char *file); 28 | 29 | // operazioni su file descriptors 30 | void xclose(int fd, int linea, char *file); 31 | 32 | 33 | // thread 34 | int xpthread_create(pthread_t *thread, const pthread_attr_t *attr, 35 | void *(*start_routine) (void *), void *arg, int linea, char *file); 36 | int xpthread_join(pthread_t thread, void **retval, int linea, char *file); 37 | 38 | // mutex 39 | int xpthread_mutex_init(pthread_mutex_t *restrict mutex, const pthread_mutexattr_t *restrict attr, int linea, char *file); 40 | int xpthread_mutex_destroy(pthread_mutex_t *mutex, int linea, char *file); 41 | int xpthread_mutex_lock(pthread_mutex_t *mutex, int linea, char *file); 42 | int xpthread_mutex_unlock(pthread_mutex_t *mutex, int linea, char *file); 43 | 44 | // barrier 45 | int xpthread_barrier_init(pthread_barrier_t *restrict barrier, const pthread_barrierattr_t *restrict attr, 46 | unsigned int count, int linea, char *file); 47 | int xpthread_barrier_destroy(pthread_barrier_t *barrier, int linea, char *file); 48 | int xpthread_barrier_wait(pthread_barrier_t *barrier, int linea, char *file); 49 | 50 | // condition variables 51 | int xpthread_cond_init(pthread_cond_t *restrict cond, const pthread_condattr_t *restrict attr, int linea, char *file); 52 | int xpthread_cond_destroy(pthread_cond_t *cond, int linea, char *file); 53 | int xpthread_cond_wait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex, int linea, char *file); 54 | int xpthread_cond_signal(pthread_cond_t *cond, int linea, char *file); 55 | int xpthread_cond_broadcast(pthread_cond_t *cond, int linea, char *file); 56 | 57 | 58 | // semafori named e unnamed POSIX 59 | sem_t *xsem_open(const char *name, int oflag, mode_t mode, unsigned int value, int linea, char *file); 60 | int xsem_unlink(const char *name, int linea, char *file); 61 | int xsem_close(sem_t *sem, int linea, char *file); 62 | int xsem_init(sem_t *sem, int pshared, unsigned int value, int linea, char *file); 63 | int xsem_destroy(sem_t *sem, int linea, char *file); 64 | int xsem_post(sem_t *sem, int linea, char *file); 65 | int xsem_wait(sem_t *sem, int linea, char *file); 66 | 67 | // operazioni su processi 68 | pid_t xfork(int linea, char *file); 69 | pid_t xwait(int *status, int linea, char *file); 70 | // pipes 71 | int xpipe(int pipefd[2], int linea, char *file); 72 | 73 | // memoria condivisa POSIX 74 | int xshm_open(const char *name, int oflag, mode_t mode, int linea, char *file); 75 | int xshm_unlink(const char *name, int linea, char *file); 76 | int xftruncate(int fd, off_t length, int linea, char *file); 77 | void *simple_mmap(size_t length, int fd, int linea, char *file); 78 | int xmunmap(void *addr, size_t length, int linea, char *file); 79 | -------------------------------------------------------------------------------- /10segnali/xerrori.h: -------------------------------------------------------------------------------- 1 | #define _GNU_SOURCE // permette di usare estensioni GNU 2 | #include // permette di usare scanf printf etc ... 3 | #include // conversioni stringa exit() etc ... 4 | #include // gestisce tipo bool 5 | #include // permette di usare la funzione ass 6 | #include // funzioni per stringhe 7 | #include // richiesto per usare errno 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include /* For mode constants */ 16 | #include /* For O_* constants */ 17 | #include 18 | 19 | // termina programma 20 | void termina(const char *s); 21 | void xtermina(const char *s, int linea, char *file); 22 | 23 | // invia messaggio d'errore su stderr 24 | void xperror(int en, char *msg); 25 | 26 | // operazioni su FILE * 27 | FILE *xfopen(const char *path, const char *mode, int linea, char *file); 28 | 29 | // operazioni su file descriptors 30 | void xclose(int fd, int linea, char *file); 31 | 32 | 33 | // thread 34 | int xpthread_create(pthread_t *thread, const pthread_attr_t *attr, 35 | void *(*start_routine) (void *), void *arg, int linea, char *file); 36 | int xpthread_join(pthread_t thread, void **retval, int linea, char *file); 37 | 38 | // mutex 39 | int xpthread_mutex_init(pthread_mutex_t *restrict mutex, const pthread_mutexattr_t *restrict attr, int linea, char *file); 40 | int xpthread_mutex_destroy(pthread_mutex_t *mutex, int linea, char *file); 41 | int xpthread_mutex_lock(pthread_mutex_t *mutex, int linea, char *file); 42 | int xpthread_mutex_unlock(pthread_mutex_t *mutex, int linea, char *file); 43 | 44 | // barrier 45 | int xpthread_barrier_init(pthread_barrier_t *restrict barrier, const pthread_barrierattr_t *restrict attr, 46 | unsigned int count, int linea, char *file); 47 | int xpthread_barrier_destroy(pthread_barrier_t *barrier, int linea, char *file); 48 | int xpthread_barrier_wait(pthread_barrier_t *barrier, int linea, char *file); 49 | 50 | // condition variables 51 | int xpthread_cond_init(pthread_cond_t *restrict cond, const pthread_condattr_t *restrict attr, int linea, char *file); 52 | int xpthread_cond_destroy(pthread_cond_t *cond, int linea, char *file); 53 | int xpthread_cond_wait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex, int linea, char *file); 54 | int xpthread_cond_signal(pthread_cond_t *cond, int linea, char *file); 55 | int xpthread_cond_broadcast(pthread_cond_t *cond, int linea, char *file); 56 | 57 | 58 | // semafori named e unnamed POSIX 59 | sem_t *xsem_open(const char *name, int oflag, mode_t mode, unsigned int value, int linea, char *file); 60 | int xsem_unlink(const char *name, int linea, char *file); 61 | int xsem_close(sem_t *sem, int linea, char *file); 62 | int xsem_init(sem_t *sem, int pshared, unsigned int value, int linea, char *file); 63 | int xsem_destroy(sem_t *sem, int linea, char *file); 64 | int xsem_post(sem_t *sem, int linea, char *file); 65 | int xsem_wait(sem_t *sem, int linea, char *file); 66 | 67 | // operazioni su processi 68 | pid_t xfork(int linea, char *file); 69 | pid_t xwait(int *status, int linea, char *file); 70 | // pipes 71 | int xpipe(int pipefd[2], int linea, char *file); 72 | 73 | // memoria condivisa POSIX 74 | int xshm_open(const char *name, int oflag, mode_t mode, int linea, char *file); 75 | int xshm_unlink(const char *name, int linea, char *file); 76 | int xftruncate(int fd, off_t length, int linea, char *file); 77 | void *simple_mmap(size_t length, int fd, int linea, char *file); 78 | int xmunmap(void *addr, size_t length, int linea, char *file); 79 | -------------------------------------------------------------------------------- /03assembler/bespin2.conf: -------------------------------------------------------------------------------- 1 | # 2 | # This file was generated from a textmate theme named Bespin 3 | # with tm2gtksw2 tool. (Alexandre da Silva) 4 | 5 | # This library is free software; you can redistribute it and/or 6 | # modify it under the terms of the GNU Library General Public 7 | # License as published by the Free Software Foundation; either 8 | # version 2 of the License, or (at your option) any later version. 9 | 10 | # This library is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | # Library General Public License for more details. 14 | 15 | # You should have received a copy of the GNU Library General Public 16 | # License along with this library; if not, write to the 17 | # Free Software Foundation, Inc., 59 Temple Place - Suite 330, 18 | # Boston, MA 02111-1307, USA. 19 | # 20 | # Ported to Geany by Matthew Brush 21 | # 22 | 23 | [theme_info] 24 | name=Bespin 2.0 25 | description=A port of the Bespin theme. 26 | # incremented automatically, do not change manually 27 | version=1225 28 | author=Alexandre da Silva (tm2gtksw2) 29 | url=https://github.com/gmate/gmate/blob/master/styles/Bespin.xml 30 | # list of each compatible Geany release version 31 | compat=1.22;1.23;1.23.1;1.24 32 | 33 | [named_styles] 34 | 35 | default=#eee;#28211c;false;false 36 | error=#f8f8f8;#4a2947 37 | 38 | # Editor styles 39 | #------------------------------------------------------------------------------- 40 | 41 | selection=#baae9e;#4c4a49;true;true 42 | current_line=#000;#2e2723;true 43 | brace_good=#00f;#2e2723;true;false 44 | brace_bad=#df4545;#2e2723;true;false 45 | margin_line_number=#baae9e;#2e2723 46 | margin_folding=#baae9e;#2e2723 47 | fold_symbol_highlight=#2e2723 48 | indent_guide=#40342c 49 | white_space=#40342c;#fff;true;false 50 | caret=#a7a7a7;#000;false 51 | marker_line=#000;#ff0; 52 | marker_search=#000;#0000f0; 53 | marker_mark=#000;#b8f4b8; 54 | call_tips=#c0c0c0;#fff;false;false 55 | 56 | # Programming languages 57 | #------------------------------------------------------------------------------- 58 | 59 | comment=#cec;;;true 60 | comment_doc=comment 61 | comment_line=comment 62 | comment_line_doc=comment_doc 63 | comment_doc_keyword=comment_doc,bold 64 | comment_doc_keyword_error=comment_doc,italic 65 | 66 | number=#cf6a4c 67 | number_1=number 68 | number_2=number_1 69 | 70 | type=#9b859d;;true 71 | class=type 72 | function=#937121 73 | parameter=function 74 | 75 | keyword=#5ea6ea;;true 76 | keyword_1=keyword 77 | keyword_2=type 78 | keyword_3=keyword_1 79 | keyword_4=keyword_1 80 | 81 | identifier=default 82 | identifier_1=identifier 83 | identifier_2=identifier_1 84 | identifier_3=identifier_1 85 | identifier_4=identifier_1 86 | 87 | string=#54be0d 88 | string_1=string 89 | string_2=string_1 90 | string_3=default 91 | string_4=default 92 | string_eol=string_1,italic 93 | character=string_1 94 | backticks=string_2 95 | here_doc=string_2 96 | 97 | scalar=string_2 98 | label=default,bold 99 | preprocessor=#cf6a4c 100 | regex=#e9c062 101 | operator=#C0E0FF 102 | decorator=string_1,bold 103 | other=#ddf2a4 104 | 105 | # Markup-type languages 106 | #------------------------------------------------------------------------------- 107 | 108 | tag=#ac885b 109 | tag_unknown=#ac885b 110 | tag_end=#ac885b 111 | attribute=#937121 112 | attribute_unknown=#937121 113 | value=string_1 114 | entity=default 115 | 116 | # Diff 117 | #------------------------------------------------------------------------------- 118 | 119 | line_added=#f8f8f8;#253b22 120 | line_removed=#f8f8f8;#420e09 121 | line_changed=#f8f8f8;#4a410d 122 | -------------------------------------------------------------------------------- /06python/PyvsC.py: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env python3 2 | 3 | import sys 4 | 5 | # esempi fatti a lezione: premere Run per leggere il file 6 | # dentro l'interprete (tab Console) e sperimentare 7 | 8 | # tre modi diversi di delimitare una stringa 9 | s1 = "ciao 1" 10 | s2 = 'ciao 2' 11 | s3 = """ciao! 12 | sono una stringa come le altre ma contengo dei \\n al 13 | mio interno infatti sono chiamata stringa 'multiriga'""" 14 | 15 | # i caratteri che non sono usati come delimitatori 16 | # possono comparire dentro la stringa 17 | s4 = 'Zinédine Zidane detto "Zizou"' 18 | 19 | 20 | # stampa delle stringhe definite prima altrimenti non sarebbero visualizzate 21 | # notiamo che la print di default aggiunge uno \n dopo aver stampato 22 | print(s1) 23 | print(s2) 24 | print(s3) 25 | print(s4) 26 | print("---- fine stringhe----") 27 | 28 | # esempio di funzione che restituisce due 29 | # valori 30 | def fun(a,b): 31 | """restituisce somma e concatenazione""" 32 | return a+b,str(a) +str(b) 33 | 34 | 35 | # esempio di ricorsione, asserzione, if/else/elsif 36 | def fatt(n): 37 | """calcola il fattoriale""" 38 | 39 | assert n>=0, "Argomento non puo essere negativo" 40 | if n==0: 41 | return 1 42 | elif n==1: 43 | return 1 44 | elif n==2: 45 | return 2 46 | else: 47 | return n*fatt(n-1) 48 | 49 | 50 | def primo(n): 51 | """esempio ciclo while con clausola else""" 52 | assert n>1, f"argomento {n} deve essere >1" 53 | d=2 54 | while d*d<=n: 55 | if n%d==0: 56 | print(f"Il numero {n} è divisibile per {d}") 57 | break 58 | d += 1 59 | else: 60 | print(f"Il numero {n} è primo") 61 | return 62 | 63 | 64 | # fattoriale senza ricorsione 65 | # avendo lo stesso nome sovrascrive la 66 | # precedente definizione di fatt() 67 | def fatt(n): 68 | assert n>=0, "Argomento non puo essere negativo" 69 | f = 1 70 | for i in range(2,n+1): 71 | f *= i 72 | return f 73 | 74 | 75 | # esempio di uso del ciclo for decrescente 76 | def contoallarovescia(n): 77 | """stampa i numeri da n a 0 78 | andando indietro di 1 alla volta""" 79 | 80 | tot = 0 81 | for i in range(n,-1,-1): 82 | print(i) 83 | tot +=i 84 | # due modi diversi per stampare la stessa informazione 85 | print( "fine, la somma è:", tot) 86 | print(f"fine, la somma è: {tot}") 87 | 88 | 89 | # esempio creazione e manipolazione lista 90 | def esempio_lista(): 91 | lista = [1,2,3,"ciao"] 92 | print(lista[2:]) # estrae gli elementi da lista[2] alla fine 93 | lista[2] = 5 94 | lista = lista + [34,40] 95 | lista.append(35) 96 | print(lista) 97 | 98 | # esempio for sugli elementi di una lista 99 | def esempio_for_lista(): 100 | parole = ["casa","mare","sole"] 101 | # prima versione senza usare un indice 102 | for x in parole: # itera tra gli elementi di parole 103 | print(x.upper()) 104 | print(parole) 105 | # seconda versione 106 | for i in range(len(parole)): # itera tra 0 e len(parole)-1 107 | print(parole[i].upper()) # questo non modifica parole[i] 108 | parole[i] = parole[i] + str(i) # qui invece parole[i] cambia 109 | print(parole) 110 | 111 | 112 | # la funzione main non ha particolari proprietà in python ... 113 | def main(n): 114 | print(f"Fattoriale di {n}: {fatt(n)}") 115 | 116 | 117 | 118 | # ma per analogia con il C spesso la usiamo 119 | # per far partire l'esecuzione del programma 120 | # ma deve essere fatto esplicitamente come qui sotto 121 | 122 | # il contenuto della linea di comando si trova 123 | # in sys.argv, perché ho fatto import sys 124 | if len(sys.argv)==2: 125 | main(int(sys.argv[1])) 126 | else: 127 | print(f"Uso: {sys.argv[0]} intero_positivo") 128 | 129 | -------------------------------------------------------------------------------- /07threads/tabella_primi.c: -------------------------------------------------------------------------------- 1 | #include "xerrori.h" 2 | 3 | // costruzione di una tabella di primi con thread multipli 4 | 5 | // questo programma è stato ottenuto partendo da 6 | // contaprimi.c aggiungendo la gestione di una tabella 7 | // e l'uso di un mutex per garantire l'accesso 8 | // esclusivo alla tabella da parte dei thread consumatori 9 | 10 | // usare lo script numeri.py per generare un file di testo 11 | // di cui sapete il numero e la somma dei primi 12 | 13 | 14 | //Prototipi 15 | bool primo(int n); 16 | 17 | // struct che uso per passare argomenti ai thread 18 | typedef struct { 19 | int start; // intervallo dove cercare i primo 20 | int end; // parametri di input 21 | int somma_parziale; // parametro di output 22 | int *tabella; // tabella dei numeri primi da riempire 23 | int *pmessi; // puntatore a indice in tabella 24 | pthread_mutex_t *pmutex; // mutex condiviso 25 | } dati; 26 | 27 | // funzione passata a pthred_create 28 | void *tbody(void *v) { 29 | dati *d = (dati *) v; 30 | int primi = 0; 31 | // cerco i primi nell'intervallo assegnato 32 | for(int j=d->start;jend;j++) 33 | if(primo(j)) { 34 | primi++; 35 | xpthread_mutex_lock(d->pmutex,__LINE__, __FILE__); 36 | d->tabella[*(d->pmessi)] = j; 37 | *(d->pmessi) += 1; 38 | xpthread_mutex_unlock(d->pmutex,__LINE__, __FILE__); 39 | } 40 | fprintf(stderr, "Il thread che partiva da %d ha terminato\n", d->start); 41 | d->somma_parziale = primi; 42 | pthread_exit(NULL); 43 | } 44 | 45 | int main(int argc,char *argv[]) 46 | { 47 | if(argc!=3) { 48 | fprintf(stderr,"Uso\n\t%s m num_threads\n", argv[0]); 49 | exit(1); 50 | } 51 | // conversione input 52 | int m= atoi(argv[1]); 53 | if(m<1) termina("limite primi non valido"); 54 | int p= atoi(argv[2]); 55 | if(p<=0) termina("numero di thread non valido"); 56 | 57 | // definizione mutex 58 | pthread_mutex_t mtabella; 59 | xpthread_mutex_init(&mtabella,NULL,__LINE__, __FILE__); 60 | // creazione thread ausiliari 61 | pthread_t t[p]; // array di p indentificatori di thread 62 | dati d[p]; // array di p struct che passerò allle p thread 63 | int *tabella = malloc(m*sizeof(int)); 64 | if(tabella==NULL) xtermina("Allocazione fallita", __LINE__, __FILE__); 65 | int messi = 0; 66 | for(int i=0; i 0 # I valori del file devono essere positivi 44 | sem_free_slots.acquire() 45 | with buffer_lock: 46 | buffer.put(n) 47 | sem_data_items.release() 48 | except FileNotFoundError: 49 | print(f"Errore: file {nomefile} non trovato") 50 | print(f"[P] Produttore con file {nomefile} terminato") 51 | 52 | def main(): 53 | if len(sys.argv) < 2: 54 | print(f"Uso: {sys.argv[0]} file1 [file2 file3 ... filek]") 55 | sys.exit(1) 56 | 57 | cons = 3 # Numero di thread consumatori 58 | assert cons > 0 59 | prod = len(sys.argv) - 1 # Numero di thread produttori 60 | assert prod > 0 61 | 62 | tot_primi = 0 63 | tot_somma = 0 64 | 65 | # Buffer condiviso 66 | buffer = queue.Queue(maxsize=10) 67 | buffer_lock = threading.Lock() 68 | 69 | # Semafori 70 | sem_free_slots = threading.Semaphore(10) 71 | sem_data_items = threading.Semaphore(0) 72 | 73 | # Creazione e avvio dei thread consumatori 74 | results = [None] * cons 75 | consumer_threads = [] 76 | for i in range(cons): 77 | t = threading.Thread(target=cbody, args=(buffer, buffer_lock, sem_free_slots, sem_data_items, results, i)) 78 | consumer_threads.append(t) 79 | t.start() 80 | print("Thread consumatori creati") 81 | 82 | # Creazione e avvio dei thread produttori 83 | producer_threads = [] 84 | for i in range(prod): 85 | t = threading.Thread(target=pbody, args=(sys.argv[i + 1], buffer, buffer_lock, sem_free_slots, sem_data_items)) 86 | producer_threads.append(t) 87 | t.start() 88 | print("Thread produttori creati") 89 | 90 | # Attesa della terminazione dei thread produttori 91 | for t in producer_threads: 92 | t.join() 93 | 94 | # Scrittura dei segnali di terminazione per i consumatori 95 | for _ in range(cons): 96 | sem_free_slots.acquire() 97 | with buffer_lock: 98 | buffer.put(-1) 99 | sem_data_items.release() 100 | print("Valori di terminazione scritti") 101 | 102 | # Attesa della terminazione dei thread consumatori e calcolo del risultato 103 | for t in consumer_threads: 104 | t.join() 105 | 106 | for quanti, somma in results: 107 | tot_primi += quanti 108 | tot_somma += somma 109 | 110 | print(f"Trovati {tot_primi} primi con somma {tot_somma}") 111 | 112 | if __name__ == "__main__": 113 | main() -------------------------------------------------------------------------------- /07threads/quicksort.c: -------------------------------------------------------------------------------- 1 | // template per quicksort con partizionamento parallelo 2 | // 3 | #define _GNU_SOURCE // avverte che usiamo le estensioni GNU 4 | #include // permette di usare scanf printf etc ... 5 | #include // conversioni stringa/numero exit() etc ... 6 | #include // gestisce tipo bool 7 | #include // permette di usare la funzione assert 8 | #include // funzioni per stringhe 9 | #include "xerrori.h" 10 | 11 | // prototipi delle funzioni che appaiono dopo il main() 12 | int *random_array(int n, int seed); 13 | void quicksort(int b[], int n); 14 | 15 | 16 | // ordina gli interi passati sulla linea di comando 17 | int main(int argc, char *argv[]) 18 | { 19 | if(argc!=3) { 20 | fprintf(stderr, "Uso:\n\t %s num_interi seed\n", argv[0]); 21 | exit(1); 22 | } 23 | int n = atoi(argv[1]); 24 | assert(n>0); 25 | // genera array random di n elementi 26 | int *a = random_array(n,atoi(argv[2])); 27 | // calcola somma prima dell'ordinamento 28 | long somma=0; 29 | for(int i=0;ia[i]) { 39 | printf("Array non ordinato alla posizione %d (%d>%d)\n",i,a[i-1],a[i]); 40 | exit(1); 41 | } 42 | } 43 | if(somma!=somma2) { 44 | printf("Somma degli elementi non corrisponde: %ld vs %ld\n",somma,somma2); 45 | exit(1); 46 | } 47 | else 48 | puts("Array ordinato e somma mantenuta, sorting probabilmente OK"); 49 | 50 | // dealloco l'array e termino 51 | free(a); 52 | return 0; 53 | } 54 | 55 | 56 | 57 | // procedura di partizionamento di un array a[0..n-1] 58 | // partiziona l'array in due parti in modo che gli elementi 59 | // della prima parte sono <= degli elementi della seconda parte 60 | // restituisce il numero di elementi nelal prima parte 61 | int partition(int a[], int n) 62 | { 63 | assert(n>1); 64 | // scelgo pivot in posizione random 65 | int k = random() % n; // genero posizione random del pivot 66 | int pivot = a[k]; // elemento pivot 67 | a[k]=a[0];a[0]=pivot; // scambia a[k]<->a[0] per mettere il pivot in a[0] 68 | 69 | // procedura di partizionamento 70 | // l'elemento pivot svolge anche la funzione di sentinella 71 | int i= -1; // puntatore oltre estremo sinistro 72 | int j = n; //puntatore oltre estremo destro 73 | while(1) { 74 | while(a[--j]>pivot) 75 | ; // esce se a[j]<=pivot 76 | while(a[++i]=pivot 78 | if(i a[j] 80 | int t=a[i]; a[i]=a[j]; a[j]=t; 81 | } 82 | else break; 83 | } 84 | // la prima meta' e' a[0] .. a[j] quindi ha j+1 elementi 85 | assert(j+1 >0); 86 | assert(j+1 < n); 87 | return j+1; 88 | } 89 | 90 | 91 | // Quicksort: ordina array a[0]...a[n-1] 92 | // Notate che tutto il lavoro viene fatto da partition! 93 | void quicksort(int b[], int n) { 94 | if(n>1) { 95 | int q = partition(b,n); 96 | assert(q>0 && q0); 108 | srandom(seed); 109 | int *a = malloc(n* sizeof(int)); 110 | assert(a!=NULL); 111 | for(int i=0;i // permette di usare scanf printf etc ... 3 | #include // conversioni stringa/numero exit() etc ... 4 | #include // gestisce tipo bool (per variabili booleane) 5 | #include // permette di usare la funzione assert 6 | #include // funzioni di confronto/copia/etc di stringhe 7 | 8 | // Come detto a lezione, le istruzioni #include qui sopra 9 | // leggono dei file che contengono i prototipi delle funzioni 10 | // di libreria che usiamo nel programma (tipo malloc/printf/exit ...) 11 | // Quale include deve essere specificato per ogni funzione 12 | // è indicato nella pagina man della funzione 13 | 14 | // Per ottenere la lista delle directory nelle quali i file .h 15 | // vengono cercati dal compilatore scrivete sulla linea di comando 16 | // gcc -xc /dev/null -E -Wp,-v 2>&1 | sed -n 's,^ ,,p' 17 | 18 | 19 | // da compilare con: 20 | // gcc -std=c11 -Wall -O -g -o primi primi.c 21 | 22 | 23 | // Scopo del programma: 24 | // legge un intero N da tastiera 25 | // crea un array *dinamico* con i primi <=N 26 | 27 | // prototipo della funzione primo() 28 | // bool primo(int k); 29 | // non necessario in quanto la definizione è prima del main 30 | 31 | // prototipo della funzione termina() 32 | // il corpo della funzione può apparire dopo il main() 33 | void termina(char *messaggio); 34 | 35 | 36 | // dato k restituisco True se è primo, false altrimenti 37 | // suggerito da copilot (non è bellissimo ma è corretto) 38 | bool primo(int k) { 39 | // se k è pari e diverso da 2 allora non è primo 40 | if(k%2==0 && k!=2) return false; 41 | // se k è dispari e non è primo 42 | // allora esiste un divisore <= sqrt(k) 43 | // che è dispari 44 | // quindi posso controllare solo i divisori dispari 45 | // e posso fermarmi a sqrt(k) 46 | for(int i=3; i*i<=k; i+=2) { 47 | if(k%i==0) return false; 48 | } 49 | return true; 50 | } 51 | 52 | 53 | 54 | 55 | 56 | int main(int argc, char *argv[]) 57 | { 58 | int n; // definisco variabile intera di nome n 59 | 60 | // spiego cosa voglio leggere e lo leggo con scanf 61 | printf("Inserisci il valore N: "); 62 | int e = scanf("%d",&n); // il motivo della & lo vedremo più avanti 63 | // controlli sulla lettura 64 | if(e!=1) termina("Valore non trovato"); 65 | if(n<2) termina("Non ci sono numeri primi"); 66 | 67 | 68 | // crea un array dinamico inizialmente di 10 elementi 69 | int *a; // dichiaro che a sarà usata come array 70 | int capacita = 10; // dimensione attuale dell'array 71 | int messi = 0; // numero di elementi attualmente dentro l'array 72 | a = malloc(capacita*sizeof(int)); 73 | if(a==NULL) 74 | termina("Malloc fallita"); 75 | 76 | 77 | // riempio array 78 | for(int i=2; i<=n; i++) { 79 | if(primo(i)) { 80 | // se l'intero i è primo lo inserisco 81 | // nella tabella dei primi 82 | // ma prima verifico che ci sia spazio 83 | if(messi==capacita) { 84 | capacita = 2*capacita; // se la tabella è piena raddoppio la dimensione 85 | a = realloc(a,capacita*sizeof(int)); 86 | if(a==NULL) 87 | termina("Realloc fallita"); 88 | } 89 | // inserisco il primo i dentro a[] 90 | a[messi] = i; 91 | messi += 1; 92 | } 93 | } 94 | // tabella completata 95 | // riduco array alla dimensione minima 96 | capacita = messi; 97 | a = realloc(a,capacita*sizeof(int)); 98 | if(a==NULL) termina("Realloc fallita"); 99 | 100 | // stampa contenuto array, usando 8 caratteri per intero 101 | for(int i=0;i // permette di usare scanf printf etc ... 3 | #include // conversioni stringa exit() etc ... 4 | #include // gestisce tipo bool 5 | #include // permette di usare la funzione ass 6 | #include // funzioni per stringhe 7 | #include // richiesto per usare errno 8 | #include 9 | #include "strint.h" 10 | 11 | // definiamo come costannte di compilazione 12 | // la stringa di tutti i delimitatori tra le parole 13 | #define Delimitatori " .,:;!?<>\"\n-" 14 | 15 | 16 | // prototipi delle funzioni che appaiono dopo il main() 17 | void termina(const char *messaggio); 18 | 19 | strint *crea_albero(FILE *f, int *pdistinte, int *ptot) 20 | { 21 | assert(f!=NULL); 22 | strint *root = NULL; 23 | *pdistinte = *ptot = 0; 24 | // ciclo di lettura delle linee del file 25 | char *buffer=NULL; // usata da getline() 26 | size_t n=0; // usata da getline() 27 | while(true) { 28 | ssize_t e = getline(&buffer,&n,f); // leggi singola linea 29 | if(e<0) { // se e<0 assumiamo sia finito il file 30 | free(buffer); // dealloco il buffer usato per le linee 31 | break; 32 | } 33 | // esegue la tokenizzazione di buffer: legge primo token 34 | char *s = strtok(buffer,Delimitatori); 35 | while(s!=NULL) { 36 | if(strlen(s)>0) { 37 | *ptot +=1; 38 | strint *nodo = abr_ricerca(root,s); // cerca se la stringa è gia presente 39 | if(nodo!=NULL) // se è presente incrementa intero associato 40 | nodo->n +=1; 41 | else { 42 | strint *si = strint_crea(s,1); 43 | root = abr_inserisci(root,si); 44 | *pdistinte += 1; 45 | } 46 | } 47 | // legge il prossimo token 48 | s = strtok(NULL,Delimitatori); 49 | } 50 | } // end while del getline 51 | return root; 52 | } 53 | 54 | int riempi_array_nodi(strint *root, strint *a[]) 55 | { 56 | if(root!=NULL) { 57 | int messisx = riempi_array_nodi(root->left, a); 58 | a[messisx] = root; 59 | int messidx = riempi_array_nodi(root->right, 60 | &a[messisx+1]); 61 | return 1 + messisx + messidx; 62 | } 63 | return 0; 64 | } 65 | 66 | int confronta_freq(strint **a, strint **b) 67 | { 68 | strint *pa = *a; 69 | strint *pb = *b; 70 | return pb->n - pa->n; 71 | } 72 | 73 | 74 | int main(int argc, char *argv[]) 75 | { 76 | if(argc!=2) { 77 | printf("Uso: %s nomefile\n",argv[0]); 78 | exit(1); 79 | } 80 | 81 | FILE *f = fopen(argv[1],"rt"); 82 | if(f==NULL) termina("Errore apertura input file"); 83 | // crea albero con le stringhe lette dal file 84 | int totparole, distinte; 85 | strint *root = crea_albero(f,&distinte,&totparole); 86 | fclose(f); 87 | fprintf(stderr,"Distinte: %d, #nodi: %d\n",distinte,abr_strint_totnodi(root)); 88 | fprintf(stderr,"#parole: %d, somma nodi: %d\n",totparole,abr_strint_sommanodi(root)); 89 | 90 | // creo array di puntatore ai nodi 91 | strint **a = malloc(distinte*sizeof(*a)); 92 | if(a==NULL) termina("Non riesco a crere array di nodi"); 93 | int n = riempi_array_nodi(root,a); 94 | assert(n==distinte); 95 | qsort(a,n,sizeof(*a), (__compar_fn_t) &confronta_freq); 96 | puts("---- stampa per frequenza ----"); 97 | for(int i=0;i uscenti(Nodo n); 63 | 64 | /** 65 | Restituisce l'insieme di tutti gli archi del grafo ordinati per peso crescente 66 | 67 | @return insieme di tutti gli archi del grafo 68 | */ 69 | abstract public SortedSet archi(); 70 | 71 | /** 72 | Restituisce i cammini minimi da un nodo sorgente 73 | 74 | @parameter s sorgente per il calcolo dei cammini minimi 75 | @return mappa che associa ad ogni nodo raggiungibile da s 76 | il costo del cammino minimo e il nodo precedente 77 | */ 78 | public Map dijkstra(Nodo s) { 79 | // verifica che la sorgente sia nel grafo! 80 | assert this.contiene_nodo(s): 81 | "La sorgente deve appartenere al grafo"; 82 | 83 | // nodi per i quali ho determinato la distanza minima da s 84 | Map risolti = new LinkedHashMap(); 85 | 86 | // nodi per quali ho trovato almeno un cammino da s 87 | // per ogni nodo mantengo il segmento migliore trovato finora 88 | Map raggiunti = new HashMap(); 89 | 90 | // inizializzo raggiunti con il nodo sorgente che ha 91 | // distanza zero da se stesso 92 | raggiunti.put(s,new Cammino(s,0.0)); 93 | 94 | // continuo fino a quando ci sono nodi raggiunti ma non risolti 95 | while(raggiunti.size()>0) { 96 | // cerca tra i nodi raggiunti quello con valore associato minimo (attualmente inefficiente) 97 | Set attivi = raggiunti.keySet(); 98 | Nodo n = Collections.min(attivi, (n1,n2) -> Double.compare( 99 | raggiunti.get(n1).costo,raggiunti.get(n2).costo)); 100 | double n_minimo = raggiunti.get(n).costo; 101 | // sposta n da raggiunti a risolti 102 | risolti.put(n,raggiunti.remove(n)); 103 | // considera archi uscenti da n 104 | for(Arco a : uscenti(n)) { 105 | Nodo m = a.altro_estremo(n); 106 | double m_dist = n_minimo + a.weight; 107 | if(risolti.containsKey(m)) 108 | continue; 109 | if(!raggiunti.containsKey(m)) 110 | raggiunti.put(m,new Cammino(n,m_dist)); 111 | 112 | else if(raggiunti.get(m).costo>m_dist) { 113 | raggiunti.get(m).costo = m_dist; 114 | raggiunti.get(m).precedente = n; 115 | } 116 | } // end for Arco 117 | } // end while 118 | return risolti; 119 | } 120 | 121 | } -------------------------------------------------------------------------------- /06python/serieA.py: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env python3 2 | """ 3 | Esercizio che costruisce una classifica dati i 4 | risultati di un insieme di partite scritte in un file 5 | 6 | 7 | Uso un dizionario per rappresentare la classifica con 8 | chiave: nome squadra 9 | valore: array di 3 elementi: [punteggio, gol fatti, gol subiti] 10 | Per convenzione se una squadra non è nel dizionario 11 | assumiamo abbia punteggio 0 e 0 gol fatti o subiti 12 | 13 | La classifica finale viene costruita ordinando 14 | le squadre per punteggio e differenza reti 15 | 16 | sorting howto: 17 | https://docs.python.org/3/howto/sorting.html 18 | 19 | with statement 20 | https://realpython.com/python-with-statement/ 21 | """ 22 | 23 | 24 | # import necessario per leggere gli argomenti 25 | # sulla linea di comando in sys.argv 26 | import sys 27 | 28 | 29 | def aggiorna_classifica(c,s1,g1,s2,g2): 30 | """Aggiorna per s1 e s2 i punti i gol fatti e subiti. 31 | Per ogni squadra nella classifica associo al nome 32 | l'array di 3 elementi: [punti, gf, gs]""" 33 | # calcolo i punti assegnati alle squadre 34 | if g1>g2: 35 | p1=3 36 | p2=0 37 | elif g12 vuol dire usare 2 spazi e giustificare a destra 87 | print(f"{nome:<12} {punti:>2} {golf:>2} {gols:>2}") 88 | 89 | 90 | def main(nomefile): 91 | with open(nomefile,"r") as f: 92 | # viene restituito il dizionario c contenente la classifica 93 | c = crea_classifica(f) 94 | # all'uscita dal blocco with 95 | # il file viene automaticamente chiuso 96 | 97 | # ottengo la lista delle squadre partecipanti 98 | # trasformado in lista l'insieme delel chiavi di c 99 | squadre = list(c) # crea un array con le chiavi 100 | 101 | # ordina per valori decrescenti di punti e differenza reti 102 | # per ogni squadra x c[x] è l'array con punti,golfatti,golsubiti 103 | # quindi c[x][0] sono i punti, c[x][1]-c[x][2] la differenza reti 104 | # Usiamo il fatto che gli array di 2 elementi sono confrontati 105 | # componente per componente 106 | squadre.sort(key=lambda x: [c[x][0], c[x][1]-c[x][2]], reverse=True) 107 | # stampa intestazione classifica 108 | print("-----------------------") 109 | print("Squadra Pu GF GS") 110 | print("-----------------------") 111 | # stampo la classifica secondo l'ordinamento ottenuto 112 | for s in squadre: 113 | stampa_squadra(s,c[s][0],c[s][1],c[s][2]) 114 | 115 | 116 | if len(sys.argv)==2: 117 | main(sys.argv[1]) 118 | else: 119 | print(f"Uso:\n\t{sys.argv[0]} nomefile_risultati") 120 | 121 | -------------------------------------------------------------------------------- /08condVar/rw.c: -------------------------------------------------------------------------------- 1 | #include "xerrori.h" 2 | #define QUI __LINE__,__FILE__ 3 | 4 | 5 | // Possibile soluzione al problema lettori/scrittori 6 | // Questa soluzione senza l'uso di wpending è unfair per gli scrittori 7 | // che potrebbero essere messi in attesa indefinita 8 | // se continuano ad arrivare lettori 9 | 10 | typedef struct { 11 | int readers; 12 | bool writing; 13 | int wpending; 14 | pthread_cond_t cond; // condition variable 15 | pthread_mutex_t mutex; // mutex associato alla condition variable 16 | } rw; 17 | 18 | 19 | // inizializza rw, ne scrittori ne lettori 20 | void rw_init(rw *z) 21 | { 22 | z->readers = z->wpending = 0; 23 | z->writing = false; 24 | xpthread_cond_init(&z->cond,NULL,QUI); 25 | xpthread_mutex_init(&z->mutex,NULL,QUI); 26 | } 27 | 28 | // inizio uso da parte di un reader 29 | void read_lock(rw *z) 30 | { 31 | fprintf(stderr,"%2d read request\n", gettid()%100); 32 | pthread_mutex_lock(&z->mutex); 33 | // se si elimina il test su z->wpending si ha la soluzione unfair per gli scrittori 34 | while(z->writing==true || z->wpending>0) 35 | pthread_cond_wait(&z->cond, &z->mutex); // attende fine scrittura 36 | z->readers++; 37 | pthread_mutex_unlock(&z->mutex); 38 | } 39 | 40 | // fine uso da parte di un reader 41 | void read_unlock(rw *z) 42 | { 43 | fprintf(stderr,"%2d read completed\n", gettid()%100); 44 | pthread_mutex_lock(&z->mutex); 45 | assert(z->readers>0); // ci deve essere almeno un reader (me stesso) 46 | assert(!z->writing); // non ci devono essere writer 47 | z->readers--; // cambio di stato 48 | if(z->readers==0) 49 | pthread_cond_signal(&z->cond); // da segnalare ad un solo writer 50 | pthread_mutex_unlock(&z->mutex); 51 | } 52 | 53 | // inizio uso da parte di un writer 54 | void write_lock(rw *z) 55 | { 56 | fprintf(stderr,"%2d write request\n", gettid()%100); 57 | pthread_mutex_lock(&z->mutex); 58 | z->wpending += 1; 59 | while(z->writing || z->readers>0) 60 | // attende fine scrittura o lettura 61 | pthread_cond_wait(&z->cond, &z->mutex); 62 | z->writing = true; 63 | z->wpending -= 1; 64 | pthread_mutex_unlock(&z->mutex); 65 | } 66 | 67 | // fine uso da parte di un writer 68 | void write_unlock(rw *z) 69 | { 70 | fprintf(stderr,"%2d write completed\n", gettid()%100); 71 | pthread_mutex_lock(&z->mutex); 72 | assert(z->writing); 73 | z->writing=false; // cambio stato 74 | // segnala a tutti quelli in attesa 75 | pthread_cond_broadcast(&z->cond); 76 | pthread_mutex_unlock(&z->mutex); 77 | } 78 | 79 | 80 | void *lettore(void *arg) 81 | { 82 | rw *z = (rw *)arg; 83 | read_lock(z); 84 | sleep(1); 85 | read_unlock(z); 86 | return NULL; 87 | } 88 | 89 | void *scrittore(void *arg) 90 | { 91 | rw *z = (rw *)arg; 92 | write_lock(z); 93 | sleep(1); 94 | write_unlock(z); 95 | return NULL; 96 | } 97 | 98 | 99 | 100 | int main(int argc, char *argv[]) 101 | { 102 | rw z; 103 | rw_init(&z); 104 | // thread che usano la rw 105 | pthread_t t[20]; 106 | int i=0; 107 | xpthread_create(&t[i++],NULL, &lettore, &z, QUI); 108 | xpthread_create(&t[i++],NULL, &lettore, &z, QUI); 109 | xpthread_create(&t[i++],NULL, &scrittore, &z, QUI); 110 | xpthread_create(&t[i++],NULL, &lettore, &z, QUI); 111 | xpthread_create(&t[i++],NULL, &lettore, &z, QUI); 112 | xpthread_create(&t[i++],NULL, &lettore, &z, QUI); 113 | xpthread_create(&t[i++],NULL, &lettore, &z, QUI); 114 | xpthread_create(&t[i++],NULL, &lettore, &z, QUI); 115 | xpthread_create(&t[i++],NULL, &lettore, &z, QUI); 116 | xpthread_create(&t[i++],NULL, &scrittore, &z, QUI); 117 | xpthread_create(&t[i++],NULL, &lettore, &z, QUI); 118 | xpthread_create(&t[i++],NULL, &lettore, &z, QUI); 119 | xpthread_create(&t[i++],NULL, &lettore, &z, QUI); 120 | xpthread_create(&t[i++],NULL, &lettore, &z, QUI); 121 | // attendo tutti i thread altrimenti terminano tutti 122 | for(int j=0; j insieme = new HashSet(); 77 | try { 78 | BufferedReader br = new BufferedReader(new FileReader(args[0])); 79 | String linea; 80 | while((linea = br.readLine()) != null) { 81 | // salta linee vuote o commenti 82 | if(linea.length() == 0 || linea.charAt(0) == '#') 83 | continue; 84 | Citta c = new Citta(linea); 85 | if(insieme.add(c)!=true) 86 | System.out.println("Città duplicata: " + c); 87 | } 88 | br.close(); // chiudo il file 89 | } 90 | // esempio di gestione di una eccezione separatamente 91 | // dal caso generale: in questo caso invece di terminare 92 | // il programma, stampo un messaggio e elaboro le città lette 93 | catch (IncompleteRow e) { 94 | System.err.println(e + "\nInterrompo la lettura "); 95 | } 96 | catch(Exception e) { 97 | System.err.println("Errore: " + e); 98 | e.printStackTrace(); 99 | System.exit(2); 100 | } 101 | // stampa elenco città 102 | for(Citta c: insieme) 103 | System.out.println(c); 104 | System.out.println("---- end ----"); 105 | } 106 | } 107 | 108 | 109 | // creo una eccezione per segnalare righe incomplete 110 | // eredita da RuntimeException affinché sia un unchecked exception 111 | class IncompleteRow extends RuntimeException { 112 | IncompleteRow(String e) {super(e);} 113 | } 114 | -------------------------------------------------------------------------------- /12atomic/spinlock.c: -------------------------------------------------------------------------------- 1 | #define _GNU_SOURCE // permette di usare estensioni GNU 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | // confronto di diversi metodi per evitare race conditions 10 | // nell'aggioramento di una variabile intera condivisa 11 | 12 | // Se viene definito USE_MUTEX la race condition 13 | // viene evitata con un mutex 14 | 15 | // Se viene definito USE_ATOMIC_SUM la race condition 16 | // viene evitata meorizzando la somma in una variabile atomic_long 17 | // che quindi può essere aggiornata in maniera atomica 18 | // con la funzione atomic_fetch_add 19 | 20 | // Altrimenti la race condition viene evitata usando un 21 | // spinlock, che è una sorta di semplice mutex con attesa attiva 22 | 23 | // il make crea gli eseguibili per tutte e tre le versioni: 24 | // muspinlock.out atspinlock.out e spinlock.out 25 | 26 | // gli esperimenti mostrano che l'uso della variabile atomic è 27 | // piu veloce del mutex che e piu veloce dello spinlock 28 | // viene utilizzata una pthread barrier per far partire tutti 29 | // i thread allo stesso momento allo scopo di massimizzare la 30 | // probabilità di accessi simultanei alla variabile condivisa 31 | 32 | 33 | typedef struct { 34 | #if defined(USE_MUTEX) 35 | long *somma; // somma non atomica + mutex 36 | pthread_mutex_t *lock; 37 | #elif defined(USE_ATOMIC_SUM) 38 | atomic_long *somma; // somma atomica 39 | #else 40 | long *somma; // somma non atomica 41 | atomic_flag *lock; // spinlock 42 | #endif 43 | pthread_barrier_t *barrier; // barriera per far partire i thread contemporaneamente 44 | int num_somme; // numero di somme da eseguire 45 | } dati; 46 | 47 | void *tbody(void* arg) { 48 | dati *d = (dati *)arg; 49 | pthread_barrier_wait(d->barrier); 50 | for(int i=0;inum_somme;i++) { 51 | #if defined(USE_MUTEX) 52 | pthread_mutex_lock(d->lock); 53 | *(d->somma) += i; 54 | pthread_mutex_unlock(d->lock); 55 | #elif defined(USE_ATOMIC_SUM) 56 | atomic_fetch_add(d->somma, i); 57 | // equivalente a *(d->somma) += i; 58 | #else // spinlock 59 | while(atomic_flag_test_and_set(d->lock)) 60 | ; 61 | *(d->somma) += i;// *(d->somma) non è atomico 62 | // equivalente a False -> d->lock 63 | atomic_flag_clear(d->lock); 64 | #endif 65 | } 66 | return NULL; 67 | } 68 | 69 | 70 | 71 | int main(int argc, char* argv[]) { 72 | if(argc!=3) { 73 | fprintf(stderr, "Usage: %s \n", argv[0]); 74 | exit(EXIT_FAILURE); 75 | } 76 | int num_somme = atoi(argv[2]); 77 | int num_thread = atoi(argv[1]); 78 | pthread_t t[num_thread]; 79 | 80 | // Inizializza la struttura dati condivisa 81 | dati d; 82 | #if defined(USE_MUTEX) 83 | long somma = 0; 84 | d.somma = &somma; 85 | pthread_mutex_t mu= PTHREAD_MUTEX_INITIALIZER; 86 | d.lock = μ 87 | #elif defined(USE_ATOMIC_SUM) 88 | atomic_long somma = ATOMIC_VAR_INIT(0); 89 | d.somma = &somma; 90 | #else 91 | atomic_flag lock = ATOMIC_FLAG_INIT; 92 | d.lock = &lock; 93 | long somma=0; 94 | d.somma = &somma; 95 | #endif 96 | pthread_barrier_t b; 97 | pthread_barrier_init(&b,NULL,num_thread); 98 | d.barrier = &b; 99 | d.num_somme = num_somme; 100 | 101 | 102 | // Create threads 103 | for (int i = 0; i < num_thread; i++) { 104 | if (pthread_create(&t[i], NULL, tbody, &d) != 0) { 105 | perror("pthread_create"); 106 | exit(EXIT_FAILURE); 107 | } 108 | } 109 | // Wait for all threads to complete 110 | for (int i = 0; i < num_thread; i++) { 111 | pthread_join(t[i], NULL); 112 | } 113 | // Destroy the barrier 114 | pthread_barrier_destroy(&b); 115 | // Print the result 116 | printf("somma = %ld\n", somma); 117 | printf("Valore atteso: %ld\n", ((long)num_somme*(num_somme-1)/2)*num_thread); 118 | return 0; 119 | } 120 | 121 | --------------------------------------------------------------------------------