Changes between Version 23 and Version 24 of WikiStart


Ignore:
Timestamp:
Mar 26, 2009, 1:44:24 PM (15 years ago)
Author:
Mattia Monga
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • WikiStart

    v23 v24  
    355355
    356356
    357 === Esercizi online (per turno 2) ===
     357=== Esercizi online con la shell ===
    358358 * [http://idea.sec.dico.unimi.it/~lorenzo/SisOp0809/ Esercizi online]
     359
     360== Lezione 4 ==
     361
     362=== Slide ===
     363
     364 * '''Turno 1 (25 Marzo 2009)''': [http://homes.dico.unimi.it/sisop/lucidi0809/solab04.pdf slide] ([http://homes.dico.unimi.it/sisop/lucidi0809/solab04-handout.pdf Versione stampa])
     365
     366=== Programmi ===
     367
     368==== Esempi con la syscall `clone`, specifica di Linux ====
     369
     370 * Thread '''senza''' memoria condivisa  `threads-isolated.c`
     371 
     372{{{
     373#!c
     374#include <unistd.h>
     375#include <stdio.h>
     376#include <stdlib.h>
     377#include <signal.h>
     378#include <sched.h>
     379
     380int run(void* s)
     381{
     382        int* shared = (int*)s; /* alias per comodita` */
     383        while (shared[0] < 10) {
     384                sleep(1);
     385                printf("Processo figlio (%d). s = %d\n",
     386                       getpid(), shared[0]);
     387                if (!(shared[0] < 10)){
     388                        printf("Corsa critica!!!!\n");
     389                        abort();
     390                }
     391                shared[0] += 1;
     392        }
     393        return 0;
     394}
     395
     396
     397int main(void){
     398 
     399        int shared[2] = {0 , 0};
     400
     401        /* int clone(int (*fn)(void *),
     402         *           void *child_stack,
     403         *           int flags,
     404         *           void *arg);
     405         * crea una copia del chiamante (con le caratteristiche
     406         * specificate da flags) e lo esegue partendo da fn */
     407        if (clone(run, /* il nuovo
     408                        * processo esegue run(shared), vedi quarto
     409                        * parametro */
     410                  malloc(4096)+4096,  /* lo stack del nuovo processo
     411                                       *  (cresce verso il basso!) */
     412                  SIGCHLD, /* in questo caso la clone e` analoga alla fork */
     413                  shared) < 0){
     414                perror("Errore nella creazione");
     415                exit(1);
     416        }
     417
     418        if (clone(run, malloc(4096)+4096,  SIGCHLD, shared) < 0){
     419                perror("Errore nella creazione");
     420                exit(1);
     421        }
     422
     423        /* Isolati: ciascuno dei figli esegue 10 volte. Per il padre
     424         * shared[0] e` sempre 0 */
     425
     426        while(1) {
     427                sleep(1);
     428                printf("Processo padre. s = %d\n", shared[0]);
     429        }
     430        return 0;
     431}
     432}}}
     433
     434 * Thread '''con''' memoria condivisa `threads-shared.c`
     435
     436{{{
     437#!c
     438#include <unistd.h>
     439#include <stdio.h>
     440#include <stdlib.h>
     441#include <signal.h>
     442#include <sched.h>
     443
     444int run(void* s)
     445{
     446        int* shared = (int*)s; /* alias per comodita` */
     447        while (shared[0] < 10) {
     448                sleep(1);
     449                printf("Processo figlio (%d). s = %d\n",
     450                       getpid(), shared[0]);
     451                if (!(shared[0] < 10)){
     452                        printf("Corsa critica!!!!\n");
     453                        abort();
     454                }
     455                shared[0] += 1;
     456        }
     457        return 0;
     458}
     459
     460
     461int main(void){
     462 
     463        int shared[2] = {0 , 0};
     464
     465        /* int clone(int (*fn)(void *),
     466         *           void *child_stack,
     467         *           int flags,
     468         *           void *arg);
     469         * crea una copia del chiamante (con le caratteristiche
     470         * specificate da flags) e lo esegue partendo da fn */
     471        if (clone(run, /* il nuovo
     472                        * processo esegue run(shared), vedi quarto
     473                        * parametro */
     474                  malloc(4096)+4096,  /* lo stack del nuovo processo
     475                                       *  (cresce verso il basso!) */
     476                  CLONE_VM | SIGCHLD, /* la (virtual) memory e` condivisa */
     477                  shared) < 0){
     478                perror("Errore nella creazione");
     479                exit(1);
     480        }
     481
     482        if (clone(run, malloc(4096)+4096,  CLONE_VM | SIGCHLD, shared) < 0){
     483                perror("Errore nella creazione");
     484                exit(1);
     485        }
     486
     487        /* Memoria condivisa: i due figli nell'insieme eseguono 10 o
     488         * 11 volte: e` possibile una corsa critica. Il padre
     489         * condivide shared[0] con i figli */
     490
     491        while(1) {
     492                sleep(1);
     493                printf("Processo padre. s = %d\n", shared[0]);
     494        }
     495        return 0;
     496}
     497}}}
     498
     499 * Thread '''con''' memoria condivisa, mutua esclusione ottenuta con Peterson `threads-peterson.c`
     500
     501{{{
     502#!c#include <unistd.h>
     503#include <stdio.h>
     504#include <stdlib.h>
     505#include <signal.h>
     506#include <sched.h>
     507
     508
     509void enter_section(int process, int* turn, int* interested)
     510{
     511        int other = 1 - process;
     512        interested[process] = 1;
     513        *turn = process;
     514        while  (*turn == process && interested[other]){
     515                printf("Busy waiting di %d\n", process);
     516        }
     517}
     518
     519void leave_section(int process, int* interested)
     520{
     521        interested[process] = 0;
     522}
     523
     524int run(const int p, void* s)
     525{
     526        int* shared = (int*)s; /* alias per comodita` */
     527        while (enter_section(p, &shared[1], &shared[2]),
     528               shared[0] < 10) {
     529                sleep(1);
     530                printf("Processo figlio (%d). s = %d\n",
     531                       getpid(), shared[0]);
     532                if (!(shared[0] < 10)){
     533                        printf("Corsa critica!!!!\n");
     534                        abort();
     535                }
     536                shared[0] += 1;
     537                leave_section(p, &shared[2]);
     538        }
     539        return 0;
     540}
     541}}}
     542
     543 * Thread '''con''' memoria condivisa, mutua esclusione con TSL `threads-tsl.c`, `enter.asm`
     544
     545{{{
     546#!c
     547#include <unistd.h>
     548#include <stdio.h>
     549#include <stdlib.h>
     550#include <signal.h>
     551#include <sched.h>
     552
     553
     554void enter_section(int *s); /* in enter.asm */
     555
     556void leave_section(int *s){
     557        *s = 0;
     558}
     559
     560int run(const int p, void* s)
     561{
     562        int* shared = (int*)s; /* alias per comodita` */
     563        while (enter_section(&shared[1]),
     564               shared[0] < 10) {
     565                sleep(rand() % 3);
     566                printf("Processo figlio (%d). s = %d\n",
     567                       getpid(), shared[0]);
     568                if (!(shared[0] < 10)){
     569                        printf("Corsa critica!!!!\n");
     570                        abort();
     571                }
     572                shared[0] += 1;
     573                leave_section(&shared[1]);
     574        }
     575        return 0;
     576}
     577
     578int run0(void*s){ return run(0, s); }
     579int run1(void*s){ return run(1, s); }
     580       
     581
     582int main(void){
     583 
     584        int shared[4] = {0 , 0, 0, 0};
     585
     586        /* int clone(int (*fn)(void *),
     587         *           void *child_stack,
     588         *           int flags,
     589         *           void *arg);
     590         * crea una copia del chiamante (con le caratteristiche
     591         * specificate da flags) e lo esegue partendo da fn */
     592        if (clone(run0, /* il nuovo
     593                         * processo esegue run(shared), vedi quarto
     594                         * parametro */
     595                  malloc(4096)+4096,  /* lo stack del nuovo processo
     596                                       *  (cresce verso il basso!) */
     597                  CLONE_VM | SIGCHLD, /* la (virtual) memory e` condivisa */
     598                  shared) < 0){
     599                perror("Errore nella creazione");
     600                exit(1);
     601        }
     602
     603        if (clone(run1, malloc(4096)+4096,  CLONE_VM | SIGCHLD, shared) < 0){
     604                perror("Errore nella creazione");
     605                exit(1);
     606        }
     607
     608        /* Memoria condivisa: i due figli nell'insieme eseguono 10 o
     609         * 11 volte: e` possibile una corsa critica. Il padre
     610         * condivide shared[0] con i figli */
     611
     612        while(shared[0] < 10) {
     613                sleep(1);
     614                printf("Processo padre. s = %d %d %d %d\n",
     615                       shared[0],
     616                       shared[1],
     617                       shared[2],
     618                       shared[3]);
     619        }
     620        return 0;
     621}
     622}}}
     623
     624{{{
     625section .text
     626global enter_section
     627
     628enter_section:
     629        enter 0, 0         ; 0 bytes of local stack space
     630        mov   ebx,[ebp+8]     ; first parameter to function
     631
     632spin:   lock bts dword [ebx], 0
     633        jc spin
     634
     635        leave                   ; mov esp,ebp / pop ebp
     636        ret     
     637}}}
     638
     639{{{
     640#!sh
     641nasm -felf enter.asm
     642cc threads-tsl.c enter.o -o threads-tsl
     643}}}
     644
     645==== Esempi in Java ====
     646
     647 * Creazione di thread `Basic.java`
     648
     649{{{
     650#!java
     651class ClasseAttiva extends Thread{
     652    public void run(){
     653        while (true) {
     654            try {
     655                Thread.sleep(100);
     656            }
     657            catch(InterruptedException e){
     658                System.err.println(e);
     659            }
     660            System.out.println(this.getName());
     661        }
     662    }
     663}
     664
     665public class Basic {
     666    public static final void main(final String[] args) {
     667        ClasseAttiva o1 = new ClasseAttiva();
     668        ClasseAttiva o2 = new ClasseAttiva();
     669        o1.start();
     670        o2.start();
     671        while (true){
     672            try {
     673                Thread.sleep(100);
     674            }
     675            catch(InterruptedException e){
     676                System.err.println(e);
     677            }
     678
     679            System.out.println("Main thread");
     680        }
     681       
     682    }
     683}
     684}}}
     685
     686 * Memoria condivisa `Shared.java`
     687
     688{{{
     689#!java
     690
     691class ClasseAttiva extends Thread{
     692    protected static int shared = 0;
     693    public void run() {
     694        while (true) {
     695            if (shared >= 10) break;
     696            try {
     697                Thread.sleep(1000);
     698            }
     699            catch(InterruptedException e){
     700                System.err.println(e);
     701            }
     702            if (shared >= 10){
     703                throw new Error("Corsa critica!!!");
     704            }
     705            System.out.println(this.getName() + " s = " + shared);
     706            shared += 1;
     707        }
     708    }
     709}
     710
     711
     712
     713public class Shared {
     714    public static final void main(final String[] args) {
     715        ClasseAttiva o1 = new ClasseAttiva();
     716        ClasseAttiva o2 = new ClasseAttiva();
     717        o1.start();
     718        o2.start();
     719        while (true){
     720            try {
     721                Thread.sleep(1000);
     722            }
     723            catch(InterruptedException e){
     724                System.err.println(e);
     725            }
     726
     727            System.out.println("Main thread");
     728        }
     729       
     730    }
     731}
     732}}}
     733
     734 * Memoria condivisa, mutua esclusione ottenuta con `synchronized`, `Shared2.java`
     735
     736{{{
     737#!java
     738class ClasseAttiva extends Thread{
     739    protected static int shared = 0;
     740    protected static Object lock = new Object();
     741    public void run() {
     742        while (true) {
     743            synchronized(lock){
     744                if (shared >= 10) break;
     745                try {
     746                    Thread.sleep(1000);
     747                }
     748                catch(InterruptedException e){
     749                    System.err.println(e);
     750                }
     751                if (shared >= 10){
     752                    throw new Error("Corsa critica!!!");
     753                }
     754                System.out.println(this.getName() + " s = " + shared);
     755                shared += 1;
     756            }
     757            Thread.yield(); // non necessaria, ma favorisce lo scheduling di entrambi
     758        }
     759    }
     760}
     761
     762
     763
     764public class Shared2 {
     765    public static final void main(final String[] args) {
     766        ClasseAttiva o1 = new ClasseAttiva();
     767        ClasseAttiva o2 = new ClasseAttiva();
     768        o1.start();
     769        o2.start();
     770        while (true){
     771            try {
     772                Thread.sleep(1000);
     773            }
     774            catch(InterruptedException e){
     775                System.err.println(e);
     776            }
     777
     778            System.out.println("Main thread");
     779        }
     780       
     781    }
     782}
     783}}}
     784
     785 * Produttore e consumatore
     786
     787{{{
     788#!java
     789
     790class Actor extends Thread
     791{
     792    public Actor(String nome){
     793        super(nome);
     794    }
     795   
     796    private Magazzino shared;
     797    public final Magazzino getShared() {
     798        return shared;
     799    }
     800    public final void setShared(final Magazzino newShared) {
     801        this.shared = newShared;
     802    }
     803
     804}
     805
     806
     807class Produttore extends Actor {
     808    public Produttore(String nome, Magazzino b) {
     809        super(nome);
     810        setShared(b);
     811    }
     812   
     813    public void run(){
     814        int i = 0;
     815        while(true){
     816            System.out.println(getName() + ": Inserisco " + i + " nel buffer");
     817            getShared().put(i);
     818            i += 1;
     819        }
     820    }
     821}
     822
     823class Consumatore extends Actor{
     824    public Consumatore(String nome, Magazzino b) {
     825        super(nome);
     826        setShared(b);
     827    }
     828    public void run(){
     829        while(true){
     830            int i = getShared().get();
     831            System.out.println(getName() + ": Estraggo " + i + " dal buffer");
     832
     833        }
     834    }
     835}
     836
     837class Magazzino{
     838    public final static int SIZE = 10;
     839    private int[] memory = new int[SIZE];
     840    private int quanti = 0;
     841
     842    public final int get() {
     843        String n = Thread.currentThread().getName();
     844        synchronized(syncPC){
     845            while(isVuoto()){
     846                System.out.println(n + " ha tentato di leggere");
     847                try {
     848                    syncPC.wait();
     849                } catch (InterruptedException e) {
     850                    System.err.println(e);
     851                }
     852            }
     853            int ris = memory[--quanti];
     854            if (quanti == SIZE - 1) syncPC.notifyAll();
     855            System.out.println(n + " ha letto");
     856            return ris;
     857        }
     858    }
     859
     860    public final void put(final int newMemory) {
     861        String n = Thread.currentThread().getName();
     862        synchronized(syncPC){
     863            while (isPieno()){
     864                System.out.println(n + " ha tentato di scrivere");
     865                try {
     866                    syncPC.wait();
     867                } catch (InterruptedException e) {
     868                    e.printStackTrace(System.err);
     869                }
     870            }
     871            memory[quanti++] = newMemory;
     872            if (quanti == 1) syncPC.notifyAll();
     873            System.out.println(n + " ha scritto");
     874        }
     875    }
     876
     877    public final boolean isVuoto() {
     878        return quanti == 0;
     879    }
     880
     881    public final boolean isPieno() {
     882        return quanti == SIZE;
     883    }
     884
     885    private Object syncPC = new Object();
     886}
     887
     888
     889public class PC {
     890
     891    public static final void main(final String[] args) {
     892        Magazzino x = new Magazzino();
     893        Produttore a1 = new Produttore("Aldo", x);
     894        Produttore a2 = new Produttore("Alberto", x);
     895        Consumatore b = new Consumatore("Barbara", x);
     896        a1.start();
     897        b.start();
     898        a2.start();
     899    }
     900
     901}
     902}}}
     903
     904