/*************************************************************************************************************************************/
/*                                                                                                                                   */
/*        D E F I N I T I O N   D U   S I M U L A T E U R   D E   M E M O I R E   V I R T U E L L E                                  */
/*        A V E C   N / 2   S E R V E U R S   E T   N / 2   C L I E N T S   F O N C T I O N N A N T                                  */
/*        E N   L E C T U R E / E C R I T U R E   A V E C   S Y N C H R O N I S A T I O N  :                                         */
/*                                                                                                                                   */
/*                                                                                                                                   */
/*             *     * * * * * *   * * * * * *   * * * * * *   *         *   * * * * * *   *   * * * * * *   *         *             */
/*                        *             *        *             **        *        *        *   *         *   **        *             */
/*            * *         *             *        *             * *       *        *        *   *         *   * *       *             */
/*                        *             *        *             *  *      *        *        *   *         *   *  *      *             */
/*           *   *        *             *        *             *   *     *        *        *   *         *   *   *     *             */
/*                        *             *        * * *         *    *    *        *        *   *         *   *    *    *             */
/*          * * * *       *             *        *             *     *   *        *        *   *         *   *     *   *             */
/*                        *             *        *             *      *  *        *        *   *         *   *      *  *             */
/*         *       *      *             *        *             *       * *        *        *   *         *   *       * *             */
/*                        *             *        *             *        **        *        *   *         *   *        **             */
/*        *         *     *             *        * * * * * *   *         *        *        *   * * * * * *   *         *             */
/*                                                                                                                                   */
/*                                                                                                                                   */
/*        ATTENTION :                                                                                                                */
/*                                                                                                                                   */
/*                    Ce fichier ('$xtc/nCube.21$I') est                                                                             */
/*                  reference dans 'v $xiMd/nCube.21$I.$m4'                                                                          */
/*                  a des fins de demonstration 'WWW'.                                                                               */
/*                                                                                                                                   */
/*                                                                                                                                   */
/*        Author of '$xtc/nCube.21$I' :                                                                                              */
/*                                                                                                                                   */
/*                    Jean-Francois Colonna (LACTAMME, AAAAMMJJhhmmss).                                                              */
/*                                                                                                                                   */
/*************************************************************************************************************************************/

/*************************************************************************************************************************************/
/*                                                                                                                                   */
/*        I N C L U D E S   S T A N D A R D S  :                                                                                     */
/*                                                                                                                                   */
/*************************************************************************************************************************************/
#include  <fcntl.h>
#include  <stdio.h>
#include  <time.h>

#define   STANDARD_OUT                                                                                                                  \
                    1                                                                                                                   \
                                        /* Sortie standard...                                                                        */

/*************************************************************************************************************************************/
/*                                                                                                                                   */
/*        D E F I N I T I O N S   T R E S   G E N E R A L E S  :                                                                     */
/*                                                                                                                                   */
/*************************************************************************************************************************************/
#define   PREMIER_ELEMENT                                                                                                               \
                    0                                                                                                                   \
                                        /* Premier element de tout...                                                                */

#define   CLEAR                                                                                                                         \
                    0                                                                                                                   \
                                        /* Valeur d'effacement generale...                                                           */
#define   UNITE                                                                                                                         \
                    1                                                                                                                   \
                                        /* Unite...                                                                                  */

#ifndef   pNULL
#    define    pNULL                                                                                                                    \
                         CLEAR                                                                                                          \
                                        /* Pointeur nul. On notera le changement en 'pNULL' (un "p" ajoute devant) qui a eu lieu le  */ \
                                        /* 20041103114722 a cause du fait que d'une part le nom anterieur est utilise par '$M4'      */ \
                                        /* ('v $xiMoG/GENERE.02$Y DNULL') et que d'autre part 'v $xiMd/nCube.21$I.$m4 nCube.21.P.I'. */
#else
#endif

#define   RIEN                                                                                                                          \
                    CLEAR                                                                                                               \
                                        /* Absence...                                                                                */

#define   OK                                                                                                                            \
                    CLEAR                                                                                                               \
                                        /* Code de retour general...                                                                 */
#define   NOK                                                                                                                           \
                    (OK + UNITE)                                                                                                        \
                                        /* Negation de 'OK'...                                                                       */

#define   UNDEF                                                                                                                         \
                    31415                                                                                                               \
                                        /* Pour quelque chose d'indefini...                                                          */

/*************************************************************************************************************************************/
/*                                                                                                                                   */
/*        F O N C T I O N S   D E   B I B L I O T H E Q U E  :                                                                       */
/*                                                                                                                                   */
/*************************************************************************************************************************************/
extern    int       atoi();
extern    char      *getenv();

extern    clock_t   clock();
extern    int       system();

extern    void      *malloc();
extern    void      free();

#define   Malloc(pointeur,taille)                                                                                                       \
                    {                                                                                                                   \
                    pointeur = malloc(taille);                                                                                          \
                    if   (pointeur == pNULL)                                                                                            \
                         {                                                                                                              \
                         fprintf(stderr,"\n impossible d'allouer de la memoire");                                                       \
                         exit();                                                                                                        \
                         }                                                                                                              \
                    else                                                                                                                \
                         {                                                                                                              \
                         }                                                                                                              \
                    }                                                                                                                   \
                                        /* Procedure d'allocation memoire...                                                         */

extern    double    pow();

#define   PUISSANCE2(n)                                                                                                                 \
                    ((int)(0.001 + pow((double)(2),(double)(n))))                                                                       \
                                        /* ATTENTION, d'une part, ne pas ecrire :                                                    */ \
                                        /*                                                                                           */ \
                                        /*                   ((int)pow((FLOTTANT)(2),(FLOTTANT)(n)))                                 */ \
                                        /*                                                                                           */ \
                                        /* puisque la fonction 'pow(...)' est une fonction de la librairie C qui attend un argument  */ \
                                        /* en double precision, et d'autre part, il est imperatif d'ajouter un petit epsilon, car,   */ \
                                        /* en effet, la valeur donnee par 'PUISSANCE2(n)' est legerement inferieure a la valeur      */ \
                                        /* entiere attendue des que 'n' est plus grand que 2...                                      */

#define   Get(valeur_de_la_variable,nom_de_la_variable)                                                                                 \
                    {                                                                                                                   \
                    valeur_de_la_variable = atoi(getenv(nom_de_la_variable));                                                           \
                    }                                                                                                                   \
                                        /* Procedure de recuperation de variables d'environnement.                                   */

/*************************************************************************************************************************************/
/*                                                                                                                                   */
/*        D E F I N I T I O N   D E   L A   P R E C I S I O N  :                                                                     */
/*                                                                                                                                   */
/*************************************************************************************************************************************/
#define   CHAR                                                                                                                          \
                    unsigned char                                                                                                       \
                                        /* Type des images...                                                                        */

#define   iLONGUEUR_caractere                                                                                                           \
                    (int)sizeof(CHAR)
#define   iLONGUEUR_entier                                                                                                              \
                    (int)sizeof(int)

#define   FLOTTANT                                                                                                                      \
                    double
#define   iLONGUEUR_flottant                                                                                                            \
                    (int)sizeof(FLOTTANT)

/*************************************************************************************************************************************/
/*                                                                                                                                   */
/*        D E F I N I T I O N   D E   B A S E   D E S   M E S S A G E S  :                                                           */
/*                                                                                                                                   */
/*************************************************************************************************************************************/
extern    void      whoami();
extern    int       nread();
extern    int       nwrite();

#define   iITYPE                                                                                                                        \
                    UNDEF                                                                                                               \
                                        /* Type des operations 'read(...)' et 'write(...)', mais actuellement inutilise...           */
#define   iUNDEF                                                                                                                        \
                    UNDEF                                                                                                               \
                                        /* Valeur actuellement inutilisee de 'flag' des fonctions 'read(...)' et 'write(...)...      */
#define   ANY                                                                                                                           \
                    (-1)                                                                                                                \
                                        /* Numero d'un processeur quelconque...                                                      */

/*************************************************************************************************************************************/
/*                                                                                                                                   */
/*        D E F I N I T I O N   D E   L A   M E M O I R E   V I R T U E L L E   G L O B A L E  :                                     */
/*                                                                                                                                   */
/*                                                                                                                                   */
/*        Definition :                                                                                                               */
/*                                                                                                                                   */
/*                    Supposons que l'on dispose de 2xN                                                                              */
/*                  processeurs. Cet ensemble est decoupe                                                                            */
/*                  en deux sous-ensembles : d'une part                                                                              */
/*                  celui des clients, et d'autre part                                                                               */
/*                  celui des serveurs. Un client ne peut                                                                            */
/*                  dialoguer qu'avec un serveur...                                                                                  */
/*                                                                                                                                   */
/*                                                                                                                                   */
/*                                                                                                                                   */
/*                                       ------------------------------------------------                                            */
/*                                      |                                                                                            */
/*                  Memoire virtuelle : |                                                           (...)                            */
/*                                      |                                                                                            */
/*                                       ------------------------------------------------                                            */
/*                                                                                                                                   */
/*                                          /\                  /\                  /\                                               */
/*                                          ||                  ||                  ||                                               */
/*                                          ||                  ||                  ||                                               */
/*                                          \/                  \/                  \/                                               */
/*                                                                                                                                   */
/*                                       --------            --------            --------                                            */
/*                                      |        |          |        |          |        |                                           */
/*                  Serveurs :          | P0==S0 |          | P2==S1 |          | P4==S2 |          (...)                            */
/*                                      |        |          |        |          |        |                                           */
/*                                       --------            --------            --------                                            */
/*                                                                                                                                   */
/*                                          /\                  /\                  /\                                               */
/*                                          ||                  ||                  ||                                               */
/*                                          ||                  ||                  ||                                               */
/*                                          \/                  \/                  \/                                               */
/*                                                                                                                                   */
/*                                       ------------------------------------------------                                            */
/*                                      |                                                                                            */
/*                                      |                   commutation                             (...)                            */
/*                                      |                                                                                            */
/*                                       ------------------------------------------------                                            */
/*                                                                                                                                   */
/*                                          /\                  /\                  /\                                               */
/*                                          ||                  ||                  ||                                               */
/*                                          ||                  ||                  ||                                               */
/*                                          \/                  \/                  \/                                               */
/*                                                                                                                                   */
/*                                       --------            --------            --------                                            */
/*                                      |        |          |        |          |        |                                           */
/*                  Clients :           | P1==C0 |          | P3==C1 |          | P5==C2 |          (...)                            */
/*                                      |        |          |        |          |        |                                           */
/*                                       --------            --------            --------                                            */
/*                                                                                                                                   */
/*                                                                                                                                   */
/*                    La memoire virtuelle est donc                                                                                  */
/*                  supportee par les serveurs uniquement                                                                            */
/*                  et est lue et ecrite par les clients.                                                                            */
/*                  A chaque Client 'C' est associe un                                                                               */
/*                  serveur naturel 'S' (par exemple 'S2'                                                                            */
/*                  est associe a 'C1'), mais cela ne limite                                                                         */
/*                  aucunement les acces. Ainsi donc a un                                                                            */
/*                  client 'C' est associe naturellement                                                                             */
/*                  un fragment (dit "local") de la memoire                                                                          */
/*                  virtuelle, dans lequel il aura interet                                                                           */
/*                  travailler afin de limiter le trafic...                                                                          */
/*                                                                                                                                   */
/*************************************************************************************************************************************/
#define   LOG2_TAILLE_MEMOIRE_VIRTUELLE                                                                                                 \
                    20                                                                                                                  \
                                        /* Logarithme en base 2 de la taille de la memoire virtuelle exprimee en octets.             */
#define   TAILLE_DE_LA_MEMOIRE_VIRTUELLE                                                                                                \
                    PUISSANCE2(LOG2_TAILLE_MEMOIRE_VIRTUELLE)                                                                           \
                                        /* Taille de la memoire virtuelle exprimee en octets ; celle-ci doit etre une puissance      */ \
                                        /* de 2, d'ou cette definition partant du logarithme...                                      */

/*************************************************************************************************************************************/
/*                                                                                                                                   */
/*        D E F I N I T I O N   D U   M A P P I N G   E N T R E   L E S                                                              */
/*        P R O C E S S E U R S   E T   L A   M E M O I R E   V I R T U E L L E  :                                                   */
/*                                                                                                                                   */
/*************************************************************************************************************************************/
#define   PROCESSEURS                                                                                                                   \
                    (UNITE + UNITE)                                                                                                     \
                                        /* Nombre de types de processeurs (les "serveurs" et les "clients").                         */

#define   PREMIER_PROCESSEUR                                                                                                            \
                    PREMIER_ELEMENT                                                                                                     \
                                        /* Numero du premier processeur.                                                             */

#define   PAGE_0                                                                                                                        \
                    PREMIER_ELEMENT                                                                                                     \
                                        /* Premiere page.                                                                            */
#define   ADRESSE_ABSOLUE_0                                                                                                             \
                    PREMIER_ELEMENT                                                                                                     \
                                        /* Premiere adresse absolue.                                                                 */
#define   ADRESSE_RELATIVE_0                                                                                                            \
                    PREMIER_ELEMENT                                                                                                     \
                                        /* Premiere adresse relative.                                                                */

#define   PREMIER_SERVEUR                                                                                                               \
                    PREMIER_PROCESSEUR                                                                                                  \
                                        /* Numero du premier serveur.                                                                */
#define   NUMERO_DE_SERVEUR__NUMERO_DE_PROCESSEUR(serveur)                                                                              \
                    ((PREMIER_PROCESSEUR + ((serveur) - PREMIER_SERVEUR) * PROCESSEURS) + RIEN)                                         \
                                        /* Fonction de passage d'un numero de serveur a un numero de processeur...                   */
#define   NUMERO_DE_PROCESSEUR__NUMERO_DE_SERVEUR(processeur)                                                                           \
                    (PREMIER_SERVEUR + ((processeur) - PREMIER_PROCESSEUR) / PROCESSEURS)                                               \
                                        /* Et inverse...                                                                             */

#define   PREMIER_CLIENT                                                                                                                \
                    PREMIER_PROCESSEUR                                                                                                  \
                                        /* Numero du premier client.                                                                 */
#define   NUMERO_DE_CLIENT__NUMERO_DE_PROCESSEUR(client)                                                                                \
                    ((PREMIER_PROCESSEUR + ((client) - PREMIER_CLIENT) * PROCESSEURS) + UNITE)                                          \
                                        /* Fonction de passage d'un numero de client a un numero de processeur...                    */
#define   NUMERO_DE_PROCESSEUR__NUMERO_DE_CLIENT(processeur)                                                                            \
                    (PREMIER_CLIENT + ((processeur) - PREMIER_PROCESSEUR) / PROCESSEURS)                                                \
                                        /* Et inverse...                                                                             */

#define   ADRESSE_ABSOLUE__NUMERO_DE_PAGE(adresse)                                                                                      \
                    (PAGE_0 + (((adresse) - ADRESSE_ABSOLUE_0) / taille_de_la_memoire_virtuelle_par_serveur))                           \
                                        /* Fonction donnant le numero d'une page de la memoire virtuelle...                          */
#define   NUMERO_DE_PAGE__ADRESSE_ABSOLUE(page)                                                                                         \
                    (ADRESSE_ABSOLUE_0 + ((page) - PAGE_0) * taille_de_la_memoire_virtuelle_par_serveur)                                \
                                        /* Et inverse...                                                                             */

#define   NUMERO_DE_PAGE__SERVEUR(page)                                                                                                 \
                    (PREMIER_SERVEUR + ((page) - PAGE_0))                                                                               \
                                        /* Fonction donnant le numero d'une page de la memoire virtuelle...                          */
#define   SERVEUR__NUMERO_DE_PAGE(serveur)                                                                                              \
                    (PAGE_0 + ((serveur) - PREMIER_SERVEUR))                                                                            \
                                        /* Et inverse...                                                                             */

#define   ADRESSE_ABSOLUE__PROCESSEUR(adresse)                                                                                          \
                    NUMERO_DE_SERVEUR__NUMERO_DE_PROCESSEUR(NUMERO_DE_PAGE__SERVEUR(ADRESSE_ABSOLUE__NUMERO_DE_PAGE(adresse)))          \
                                        /* Fonction donnant le numero dans [0,N-1] du processeur supportant une adresse absolue      */ \
                                        /* donnee dans la memoire virtuelle.                                                         */
#define   PROCESSEUR__ADRESSE_ABSOLUE(processeur)                                                                                       \
                    NUMERO_DE_PAGE__ADRESSE_ABSOLUE(SERVEUR__NUMERO_DE_PAGE(NUMERO_DE_PROCESSEUR__NUMERO_DE_SERVEUR(processeur)))       \
                                        /* Et inverse...                                                                             */

#define   ADRESSE_ABSOLUE__ADRESSE_RELATIVE(adresse)                                                                                    \
                    (ADRESSE_RELATIVE_0 + (((adresse) - ADRESSE_ABSOLUE_0) % taille_de_la_memoire_virtuelle_par_serveur))               \
                                        /* Fonction donnant l'adresse relative a l'interieur d'un processeur d'adresse absolue       */ \
                                        /* donnee dans la memoire virtuelle.                                                         */

#define   EST_SERVEUR(processeur)                                                                                                       \
                    (NUMERO_DE_SERVEUR__NUMERO_DE_PROCESSEUR(NUMERO_DE_PROCESSEUR__NUMERO_DE_SERVEUR(processeur)) == processeur)        \
                                        /* Test pour savoir si un processeur est un serveur de memoire virtuelle...                  */
#define   EST_CLIENT(processeur)                                                                                                        \
                    (! EST_SERVEUR(processeur))                                                                                         \
                                        /* Test pour savoir si un processeur est un client de memoire virtuelle...                   */

#define   SERVEUR_NATUREL(client)                                                                                                       \
                    NUMERO_DE_SERVEUR__NUMERO_DE_PROCESSEUR(NUMERO_DE_PROCESSEUR__NUMERO_DE_SERVEUR(client))                            \
                                        /* Numero du serveur associe naturellement a un client...                                    */
#define   CLIENT_NATUREL(serveur)                                                                                                       \
                    NUMERO_DE_CLIENT__NUMERO_DE_PROCESSEUR(NUMERO_DE_PROCESSEUR__NUMERO_DE_CLIENT(serveur))                             \
                                        /* Numero du client associe naturellement a un serveur...                                    */

/*************************************************************************************************************************************/
/*                                                                                                                                   */
/*        D E F I N I T I O N   D E   L A   M E M O I R E   V I R T U E L L E   L O C A L E                                          */
/*        A S S O C I E E   N A T U R E L L E M E N T   A   C H A Q U E   C L I E N T  :                                             */
/*                                                                                                                                   */
/*************************************************************************************************************************************/
#define   DEBUT_DE_LA_MEMOIRE_VIRTUELLE_LOCALE                                                                                          \
                    PROCESSEUR__ADRESSE_ABSOLUE(SERVEUR_NATUREL(processeur_local))                                                      \
                                        /* Premier octet de la memoire virtuelle supportee par le serveur associe naturellement      */ \
                                        /* au processeur local.                                                                      */
#define   FIN_DE_LA_MEMOIRE_VIRTUELLE_LOCALE                                                                                            \
                    (DEBUT_DE_LA_MEMOIRE_VIRTUELLE_LOCALE + taille_de_la_memoire_virtuelle_par_serveur - UNITE)                         \
                                        /* Dernier octet de la memoire virtuelle supportee par le serveur associe naturellement      */ \
                                        /* au processeur local.                                                                      */

/*************************************************************************************************************************************/
/*                                                                                                                                   */
/*        D E F I N I T I O N   D E S   F O N C T I O N S   D E   C O M M U N I C A T I O N  :                                       */
/*                                                                                                                                   */
/*************************************************************************************************************************************/
typedef   struct    fonctions {
                              int       code_fonction;
                              int       adresse_relative;
                              int       longueur;
                              }         fonctions;
                                        /* Bloc descriptif de la fonction demandee a un serveur...                                   */
enum      Liste_des_codes_des_fonctions
          {
           DEBUT=CLEAR
          ,FIN
          ,STORE
          ,LOAD
          ,SWAP
          };
                                        /* Liste des fonctions reconnues...                                                          */
#define   iLONGUEUR_FONCTIONS                                                                                                           \
                    (int)sizeof(fonctions)                                                                                              \
                                        /* Et nombre d'octets necessaires au codage...                                               */

#define   Read(processeur,octets_a_lire,nombre_d_octets_a_lire)                                                                         \
                    {                                                                                                                   \
                    int       itype;                                                                                                    \
                    int       iflag;                                                                                                    \
                    int       longueur;                                                                                                 \
                                                                                                                                        \
                    processeur_emetteur = MAPPING(processeur);                                                                          \
                    processeur_attendu = processeur_emetteur;                                                                           \
                    iflag = iUNDEF;                                                                                                     \
                    itype = iITYPE;                                                                                                     \
                    longueur = nread(octets_a_lire,nombre_d_octets_a_lire,&processeur_attendu,&itype,&iflag);                           \
                                                                                                                                        \
                    if        (    ((processeur_attendu != processeur_emetteur) && (processeur_emetteur != ANY))                        \
                              ||   (longueur != nombre_d_octets_a_lire)                                                                 \
                               )                                                                                                        \
                              {                                                                                                         \
                              fprintf(stderr,"\n erreur de lecture");                                                                   \
                              fprintf(stderr,"\n processeur attendu=%d",processeur_attendu);                                            \
                              fprintf(stderr,"\n processeur emetteur=%d",processeur_emetteur);                                          \
                              fprintf(stderr,"\n nombre d'octets a lire=%d",nombre_d_octets_a_lire);                                    \
                              fprintf(stderr,"\n nombre d'octets recuperes=%d",longueur);                                               \
                              exit();                                                                                                   \
                              }                                                                                                         \
                    else                                                                                                                \
                              {                                                                                                         \
                              }                                                                                                         \
                    processeur_attendu = MAPPING_INVERSE(processeur_attendu);                                                           \
                    }                                                                                                                   \
                                        /* Procedure generale de lecture...                                                          */
#define   Write(processeur,octets_a_ecrire,nombre_d_octets_a_ecrire)                                                                    \
                    {                                                                                                                   \
                    int       itype;                                                                                                    \
                    int       iflag;                                                                                                    \
                    int       longueur;                                                                                                 \
                                                                                                                                        \
                    processeur_recepteur = MAPPING(processeur);                                                                         \
                    itype = iITYPE;                                                                                                     \
                    iflag = iUNDEF;                                                                                                     \
                    longueur = nwrite(octets_a_ecrire,nombre_d_octets_a_ecrire,processeur_recepteur,itype,&iflag);                      \
                    }                                                                                                                   \
                                        /* Procedure generale d'ecriture...                                                          */

static    int       il_faut_entrelacer=OK;
                                        /* Indique s'il faut entrelacer (=OK) ou pas (#OK)...                                        */
#define   ENTRELACAGE(adresse_absolue_octets)                                                                                           \
                    ((il_faut_entrelacer == OK) ? entrelacage(adresse_absolue_octets) : (adresse_absolue_octets))                       \
                                        /* Definition de la fonction d'entrelacage. Pour le supprimer, il suffit de definir :        */ \
                                        /*                                                                                           */ \
                                        /*                  #define   ENTRELACAGE(adresse_absolue_octets)                         \  */ \
                                        /*                                      adresse_absolue_octets                               */ \
                                        /*                                                                                           */

#define   validation_d_une_adresse(adresse_absolue_octets,nombre_d_octets)                                                              \
                    {                                                                                                                   \
                    if        (    ((adresse_absolue_octets) / unite_d_entrelacage)                                                     \
                              !=   (((adresse_absolue_octets) + (nombre_d_octets) - UNITE) / unite_d_entrelacage)                       \
                               )                                                                                                        \
                              {                                                                                                         \
                              fprintf(stderr                                                                                            \
                                     ,"l'intervalle [%08x,%08x] n'est pas dans une unite d'entrelacage %08x\n"                          \
                                     ,(adresse_absolue_octets)                                                                          \
                                     ,(adresse_absolue_octets) + (nombre_d_octets) - UNITE                                              \
                                     ,unite_d_entrelacage                                                                               \
                                      );                                                                                                \
                              }                                                                                                         \
                    else                                                                                                                \
                              {                                                                                                         \
                              }                                                                                                         \
                    }                                                                                                                   \
                                        /* Validation d'une adresse octets par rapport aux parametres d'entrelacage...               */

#define   Interface_load_store(fonction,adresse_absolue_octets,nombre_d_octets)                                                         \
                    int       adresse_entrelacee=UNDEF;                                                                                 \
                    fonctions Fonction;                                                                                                 \
                                                                                                                                        \
                    adresse_entrelacee=ENTRELACAGE(adresse_absolue_octets);                                                             \
                    Fonction.code_fonction = fonction;                                                                                  \
                    Fonction.adresse_relative = ADRESSE_ABSOLUE__ADRESSE_RELATIVE(adresse_entrelacee);                                  \
                    Fonction.longueur = nombre_d_octets;                                                                                \
                                        /* Definition des donnees communes a 'load(...)' et 'store(...)'.                            */

#define   load(adresse_absolue_octets,octets_a_lire,nombre_d_octets_a_lire)                                                             \
                    {                                                                                                                   \
                    Interface_load_store(LOAD,adresse_absolue_octets,nombre_d_octets_a_lire);                                           \
                                                                                                                                        \
                    validation_d_une_adresse(adresse_absolue_octets,nombre_d_octets_a_lire);                                            \
                                                                                                                                        \
                    Write(ADRESSE_ABSOLUE__PROCESSEUR(adresse_entrelacee),&Fonction,iLONGUEUR_FONCTIONS);                               \
                                        /* Transmission d'une demande de "load" de valeur...                                         */ \
                    Read(ADRESSE_ABSOLUE__PROCESSEUR(adresse_entrelacee),octets_a_lire,Fonction.longueur);                              \
                                        /* Recuperation de la valeur...                                                              */ \
                    }                                                                                                                   \
                                        /* Procedure d'acces a la valeur de 'octets_a_lire' dans la memoire virtuelle...             */
#define   store(adresse_absolue_octets,octets_a_ecrire,nombre_d_octets_a_ecrire)                                                        \
                    {                                                                                                                   \
                    Interface_load_store(STORE,adresse_absolue_octets,nombre_d_octets_a_ecrire);                                        \
                                                                                                                                        \
                    validation_d_une_adresse(adresse_absolue_octets,nombre_d_octets_a_ecrire);                                          \
                                                                                                                                        \
                    Write(ADRESSE_ABSOLUE__PROCESSEUR(adresse_entrelacee),&Fonction,iLONGUEUR_FONCTIONS);                               \
                                        /* Transmission d'une demande de "store" de valeur...                                        */ \
                    Write(ADRESSE_ABSOLUE__PROCESSEUR(adresse_entrelacee),octets_a_ecrire,Fonction.longueur);                           \
                                        /* Envoi de la valeur.                                                                       */ \
                    }                                                                                                                   \
                                        /* Procedure de rangement de la valeur de 'octets_a_ecrire' dans la memoire virtuelle...     */

#define   action_de_debut_pour_les_serveurs                                                                                             \
                    {                                                                                                                   \
                    }                                                                                                                   \
                                        /* Procedure indiquant qu'un serveur va debuter son travail...                               */
#define   action_de_fin_pour_les_serveurs                                                                                               \
                    {                                                                                                                   \
                    }                                                                                                                   \
                                        /* Procedure indiquant qu'un serveur a fini son travail...                                   */

#define   action_de_debut_pour_les_clients                                                                                              \
                    {                                                                                                                   \
                    int       processeur;                                                                                               \
                                                                                                                                        \
                    for       (processeur=PREMIER_PROCESSEUR ; processeur<(PREMIER_PROCESSEUR+nombre_total_processeurs) ; processeur++) \
                              {                                                                                                         \
                              if        (EST_SERVEUR(MAPPING(processeur)))                                                              \
                                        {                                                                                               \
                                        Interface_load_store(DEBUT,UNDEF,UNDEF);                                                        \
                                        Write(processeur,&Fonction,iLONGUEUR_FONCTIONS);                                                \
                                        /* Transmission d'une demande de debut...                                                    */ \
                                        Read(processeur,&Fonction,iLONGUEUR_FONCTIONS);                                                 \
                                        /* Et synchronisation sur le serveur en recuperant tout simplement la fonction envoyee ;     */ \
                                        /* ainsi, on ne demarre un client que lorsque tous les serveurs sont prets...                */ \
                                        }                                                                                               \
                              else                                                                                                      \
                                        {                                                                                               \
                                        }                                                                                               \
                              }                                                                                                         \
                    }                                                                                                                   \
                                        /* Procedure indiquant qu'un client va debuter son travail...                                */
#define   action_de_fin_pour_les_clients                                                                                                \
                    {                                                                                                                   \
                    int       processeur;                                                                                               \
                                                                                                                                        \
                    for       (processeur=PREMIER_PROCESSEUR ; processeur<(PREMIER_PROCESSEUR+nombre_total_processeurs) ; processeur++) \
                              {                                                                                                         \
                              if        (EST_SERVEUR(MAPPING(processeur)))                                                              \
                                        {                                                                                               \
                                        Interface_load_store(FIN,UNDEF,UNDEF);                                                          \
                                        Write(processeur,&Fonction,iLONGUEUR_FONCTIONS);                                                \
                                        /* Transmission d'une demande de fin...                                                      */ \
                                        }                                                                                               \
                              else                                                                                                      \
                                        {                                                                                               \
                                        }                                                                                               \
                              }                                                                                                         \
                    }                                                                                                                   \
                                        /* Procedure indiquant qu'un client a fini son travail...                                    */

/*************************************************************************************************************************************/
/*                                                                                                                                   */
/*        D E F I N I T I O N   D E S   F O N C T I O N S   D E   C O M M U N I C A T I O N  :                                       */
/*                                                                                                                                   */
/*************************************************************************************************************************************/
#define   MStoreC(adresse_absolue,longueur_octets,valeur)                                                                               \
                    {                                                                                                                   \
                    store(((adresse_absolue)*iLONGUEUR_caractere),&valeur,longueur_octets);                                             \
                    }                                                                                                                   \
                                        /* Procedure de rangement d'un caractere.                                                    */
#define   MLoadC(adresse_absolue,longueur_octets,valeur)                                                                                \
                    {                                                                                                                   \
                    load(((adresse_absolue)*iLONGUEUR_caractere),&valeur,longueur_octets);                                              \
                    }                                                                                                                   \
                                        /* Procedure d'acces a un caractere.                                                         */

#define   StoreC(adresse_absolue,valeur)                                                                                                \
                    {                                                                                                                   \
                    MStoreC(adresse_absolue,iLONGUEUR_caractere,valeur);                                                                \
                    }                                                                                                                   \
                                        /* Procedure de rangement d'un caractere.                                                    */
#define   LoadC(adresse_absolue,valeur)                                                                                                 \
                    {                                                                                                                   \
                    MLoadC(adresse_absolue,iLONGUEUR_caractere,valeur);                                                                 \
                    }                                                                                                                   \
                                        /* Procedure d'acces a un caractere.                                                         */

#define   MStoreI(adresse_absolue,longueur_octets,valeur)                                                                               \
                    {                                                                                                                   \
                    store(((adresse_absolue)*iLONGUEUR_entier),&valeur,longueur_octets);                                                \
                    }                                                                                                                   \
                                        /* Procedure de rangement d'un nombre entier.                                                */
#define   MLoadI(adresse_absolue,longueur_octets,valeur)                                                                                \
                    {                                                                                                                   \
                    load(((adresse_absolue)*iLONGUEUR_entier),&valeur,longueur_octets);                                                 \
                    }                                                                                                                   \
                                        /* Procedure d'acces a un nombre entier.                                                     */

#define   StoreI(adresse_absolue,valeur)                                                                                                \
                    {                                                                                                                   \
                    MStoreI(adresse_absolue,iLONGUEUR_entier,valeur);                                                                   \
                    }                                                                                                                   \
                                        /* Procedure de rangement d'un nombre entier.                                                */
#define   LoadI(adresse_absolue,valeur)                                                                                                 \
                    {                                                                                                                   \
                    MLoadI(adresse_absolue,iLONGUEUR_entier,valeur);                                                                    \
                    }                                                                                                                   \
                                        /* Procedure d'acces a un nombre entier.                                                     */

#define   MStoreF(adresse_absolue,longueur_octets,valeur)                                                                               \
                    {                                                                                                                   \
                    store(((adresse_absolue)*iLONGUEUR_flottant),&valeur,longueur_octets);                                              \
                    }                                                                                                                   \
                                        /* Procedure de rangement d'un nombre flottant.                                              */
#define   MLoadF(adresse_absolue,longueur_octets,valeur)                                                                                \
                    {                                                                                                                   \
                    load(((adresse_absolue)*iLONGUEUR_flottant),&valeur,longueur_octets);                                               \
                    }                                                                                                                   \
                                        /* Procedure d'acces a un nombre flottant.                                                   */

#define   StoreF(adresse_absolue,valeur)                                                                                                \
                    {                                                                                                                   \
                    MStoreF(adresse_absolue,iLONGUEUR_flottant,valeur);                                                                 \
                    }                                                                                                                   \
                                        /* Procedure de rangement d'un nombre flottant.                                              */
#define   LoadF(adresse_absolue,valeur)                                                                                                 \
                    {                                                                                                                   \
                    MLoadF(adresse_absolue,iLONGUEUR_flottant,valeur);                                                                  \
                    }                                                                                                                   \
                                        /* Procedure d'acces a un nombre flottant.                                                   */

/*************************************************************************************************************************************/
/*                                                                                                                                   */
/*        D E F I N I T I O N   D E S   F O N C T I O N S   D E   S Y N C H R O N I S A T I O N  :                                   */
/*                                                                                                                                   */
/*************************************************************************************************************************************/
#define   UNLOCK                                                                                                                        \
                    CLEAR                                                                                                               \
                                        /* Etat d'un verrou libre...                                                                 */
#define   LOCK                                                                                                                          \
                    (UNLOCK + UNITE)                                                                                                    \
                                        /* Etat d'un verrou occupe...                                                                */

#define   TestAndSetI(adresse_absolue,valeur)                                                                                           \
                    {                                                                                                                   \
                    int       valeur_a_forcer=valeur;                                                                                   \
                                        /* Memorisation de la valeur que l'on desire forcer ; elle est rendue necessaire a cause     */ \
                                        /* de l'ordre du 'Read(...)' et du 'Write(...)' portant sur cette valeur...                  */ \
                    int       adresse_absolue_en_octets=(adresse_absolue)*iLONGUEUR_entier;                                             \
                    Interface_load_store(SWAP,adresse_absolue_en_octets,iLONGUEUR_entier);                                              \
                                                                                                                                        \
                    Write(ADRESSE_ABSOLUE__PROCESSEUR(adresse_entrelacee),&Fonction,iLONGUEUR_FONCTIONS);                               \
                                        /* Transmission d'une demande de "swap" de valeur...                                         */ \
                    Read(ADRESSE_ABSOLUE__PROCESSEUR(adresse_entrelacee),&valeur,Fonction.longueur);                                    \
                                        /* Recuperation de la valeur avant,                                                          */ \
                    Write(ADRESSE_ABSOLUE__PROCESSEUR(adresse_entrelacee),&valeur_a_forcer,Fonction.longueur);                          \
                                        /* Puis envoi de la valeur apres...                                                          */ \
                    }                                                                                                                   \
                                        /* Procedure d'echange d'un nombre entier afin de faire des synchronisations...              */

#define   WaitVerrou(verrou_global,verrou_local)                                                                                        \
                    {                                                                                                                   \
                    int        verrou_local=LOCK;                                                                                       \
                                        /* Definition de l'etat local du verrou global de protection d'une phase critique...         */ \
                    while     (verrou_local == LOCK)                                                                                    \
                                        /* La premiere fois le verrou est a 1 afin de forcer le 'TestAndSetI(...)' qui suit. Ensuite */ \
                                        /* tant qu'il reste a 1, cela signifie qu'il etait deja a 1 dans la memoire virtuelle, et    */ \
                                        /* donc qu'un autre processeur le possede deja...                                            */ \
                              {                                                                                                         \
                              TestAndSetI(verrou_global,verrou_local);                                                                  \
                                        /* Tentative d'entree dans une phase critique...                                             */ \
                              }                                                                                                         \
                                        /* ATTENTION, on notera le desequilibre des "{" et des "}" afin que 'WaitVerrou(...)' et     */ \
                                        /* 'ClearVerrou(...)' forment une paire de parentheses...                                    */ \
                                                                                                                                        \
                                        /* Procedure d'attente sur un verrou.                                                        */
#define   ClearVerrou(verrou_global,verrou_local)                                                                                       \
                                        /* ATTENTION, on notera le desequilibre des "{" et des "}" afin que 'WaitVerrou(...)' et     */ \
                                        /* 'ClearVerrou(...)' forment une paire de parentheses...                                    */ \
                    verrou_local = UNLOCK;                                                                                              \
                    StoreI(verrou_global,verrou_local);                                                                                 \
                                        /* Sortie de la phase critique...                                                            */ \
                    }                                                                                                                   \
                                        /* Procedure de liberation d'un verrou...                                                    */

/*************************************************************************************************************************************/
/*                                                                                                                                   */
/*        M A P P I N G   E N T R E   L E S   P R O C E S S E U R S                                                                  */
/*        L O G I Q U E S   E T   L E S   P R O C E S S E U R S   P H Y S I Q U E S                                                  */
/*        P O U R   L A   M E M O I R E   V I R T U E L L E  :                                                                       */
/*                                                                                                                                   */
/*************************************************************************************************************************************/
static    int       il_faut_mapper=NOK;
                                        /* Indique s'il faut mapper (=OK) ou pas (#OK)...                                            */

#define   MAPPING(processeur)                                                                                                           \
                    ((processeur == ANY) ? processeur : (*(mapping_des_processeurs+(processeur-PREMIER_PROCESSEUR))))                   \
                                        /* Fonction de mapping...                                                                    */
#define   MAPPING_INVERSE(processeur)                                                                                                   \
                    ((processeur == ANY) ? processeur : (*(mapping_inverse_des_processeurs+(processeur-PREMIER_PROCESSEUR))))           \
                                        /* Fonction de mapping inverse...                                                            */

static    int       *mapping_des_processeurs;
static    int       *mapping_inverse_des_processeurs;
                                        /* Table de definition du mapping entre les processeurrs physiques et logiques.              */

/*************************************************************************************************************************************/
/*                                                                                                                                   */
/*        D E F I N I T I O N   D E S   I M P L A N T A T I O N S                                                                    */
/*        D A N S   L A   M E M O I R E   V I R T U E L L E  :                                                                       */
/*                                                                                                                                   */
/*************************************************************************************************************************************/
#define   UNITE_D_ENTRELACAGE                                                                                                           \
                    iLONGUEUR_flottant
static    int       unite_d_entrelacage=UNITE_D_ENTRELACAGE;
                                        /* Definition de la longueur des blocs qui ne doivent pas etre decoupes lors de l'operation  */
                                        /* d'entrelacage...                                                                          */

#define   FORMAT_DEBUT_DE_LA_MEMOIRE_VIRTUELLE                                                                                          \
                    iLONGUEUR_caractere
#define   LONGUEUR_DEBUT_DE_LA_MEMOIRE_VIRTUELLE                                                                                        \
                    CLEAR
#define   DEBUT_DE_LA_MEMOIRE_VIRTUELLE                                                                                                 \
                    IMPLANTATION_EN_MEMOIRE_VIRTUELLE(ADRESSE_ABSOLUE_0                                                                 \
                                                     ,FORMAT_IMPLICITE_DE_LA_MEMOIRE_VIRTUELLE                                          \
                                                     ,FORMAT_DEBUT_DE_LA_MEMOIRE_VIRTUELLE                                              \
                                                      )
                                        /* Emplacement du debut de la memoire virtuelle.                                             */

#define   FRONTIERE_COMMUNE                                                                                                             \
                    unite_d_entrelacage                                                                                                 \
                                        /* Toutes les implantations en memoire virtuelle se feront sur des frontieres de 'FLOTTANT'. */

#define   FORMAT_IMPLICITE_DE_LA_MEMOIRE_VIRTUELLE                                                                                      \
                    iLONGUEUR_caractere                                                                                                 \
                                        /* Pour definir le premier element implante dans la memoire virtuelle.                       */

#define   MULTIPLE_SUPERIEUR(x,base)                                                                                                    \
                    ((((x) + (base) - UNITE) / (base) ) * (base))                                                                       \
                                        /* Calcul le multiple de 'base' immediatement superieur a 'x'...                             */

#define   IMPLANTATION_EN_MEMOIRE_VIRTUELLE(adresse_precedente_plus_longueur,unite_precedente,unite_courante)                           \
                    (MULTIPLE_SUPERIEUR(((adresse_precedente_plus_longueur)*(unite_precedente)),FRONTIERE_COMMUNE) / (unite_courante))  \
                                        /* Calcul de l'adresse d'implantation en memoire virtuelle de l'element courant en fonction  */ \
                                        /* de l'adresse d'implantation de l'element precedent et de leurs unites respectives. On     */ \
                                        /* notera que l'on se place de plus a une frontiere de 'FLOTTANT'. Enfin, l'adresse de       */ \
                                        /* l'objet courant est defini par rapport a l'objet precedent translate de la longueur de    */ \
                                        /* dernier, cette longueur etant exprimee dans l'unite 'unite_precedente' : ainsi, si par    */ \
                                        /* exemple l'objet precedent 'O1' est en entier, l'adresse de l'objet suivant 'O2' sera      */ \
                                        /* 'O1+1', et ce quel que soit le type de 'O2.'...                                           */
#define   ADRESSAGE_EN_MEMOIRE_VIRTUELLE(adresse_de_l_objet,deplacement)                                                                \
                    ((adresse_de_l_objet) + (deplacement))                                                                              \
                                        /* Acces a un element 'deplacement' d'un objet 'adresse_de_l_objet'...                       */

/*************************************************************************************************************************************/
/*                                                                                                                                   */
/*        D O N N E E S   G L O B A L E S  :                                                                                         */
/*                                                                                                                                   */
/*************************************************************************************************************************************/
static    int       processeur_local;
                                        /* Identite du processeur local.                                                             */

static    int       dimension;
                                        /* Dimension (0,1,2,...) de l'hyper-cube alloue.                                             */
static    int       nproc;
                                        /* Donne dans les deux octets de poids faible la meme information que 'processeur_local',    */
                                        /* et dans les deux octets de poids forts le numero du process courant.                      */
static    int       nhost;
                                        /* Donne un identificateur 'ID' d'un programme host.                                         */
static    int       nombre_total_processeurs;
                                        /* Nombre total de processeurs disponibles.                                                  */
static    int       nombre_total_de_serveurs;
static    int       nombre_total_de_clients;
                                        /* Nombre total de serveurs et de clients.                                                   */
static    int       taille_de_la_memoire_virtuelle;
                                        /* Taille totale de la memoire virtuelle.                                                    */
static    int       taille_de_la_memoire_virtuelle_par_serveur;
                                        /* Taille de la memoire virtuelle supportee par chaque serveur.                              */

static    int       processeur_emetteur;
static    int       processeur_recepteur;
static    int       processeur_attendu;

/*************************************************************************************************************************************/
/*                                                                                                                                   */
/*        F O N C T I O N   D ' E N T R E L A C A G E   D E S   A D R E S S E S  :                                                   */
/*                                                                                                                                   */
/*************************************************************************************************************************************/
int       entrelacage(adresse_absolue)
int       adresse_absolue;
          {
          int       adresse_entrelacee=UNDEF;

          int       numero_de_page=ADRESSE_ABSOLUE__NUMERO_DE_PAGE(adresse_absolue);
          int       adresse_relative=ADRESSE_ABSOLUE__ADRESSE_RELATIVE(adresse_absolue);

          int       bits_de_poids_faibles_de_l_adresse_relative=UNDEF;
          int       bits_de_poids_forts_et_moyens_de_l_adresse_relative=UNDEF;
          int       bits_de_poids_moyens_de_l_adresse_relative=UNDEF;
          int       bits_de_poids_forts_de_l_adresse_relative=UNDEF;

          bits_de_poids_faibles_de_l_adresse_relative = (adresse_relative % unite_d_entrelacage);
          bits_de_poids_forts_et_moyens_de_l_adresse_relative = (adresse_relative / unite_d_entrelacage);
          bits_de_poids_moyens_de_l_adresse_relative = (bits_de_poids_forts_et_moyens_de_l_adresse_relative % nombre_total_de_serveurs);
          bits_de_poids_forts_de_l_adresse_relative = (bits_de_poids_forts_et_moyens_de_l_adresse_relative / nombre_total_de_serveurs);

          adresse_entrelacee = NUMERO_DE_PAGE__ADRESSE_ABSOLUE(SERVEUR__NUMERO_DE_PAGE(bits_de_poids_moyens_de_l_adresse_relative))
                               + ((bits_de_poids_forts_de_l_adresse_relative*nombre_total_de_serveurs)
                               + numero_de_page)*unite_d_entrelacage
                               + bits_de_poids_faibles_de_l_adresse_relative;
                                        /* Definition de l'entrelacage :                                                             */
                                        /*                                                                                           */
                                        /*                   -----------------------------------------------------------             */
                                        /*                  |              |              |              |              |            */
                                        /* adresse absolue  |    numero    |    poids     |    poids     |    poids     |            */
                                        /* non  entrelacee  |   de  page   |    forts     |    moyens    |   faibles    |            */
                                        /*                  |              |              |              |              |            */
                                        /*                   -----------------------------------------------------------             */
                                        /*                  .              .              .              .              .            */
                                        /*                  .              .              .              .              .            */
                                        /*                  .    nombre    .              .   nombre     . longueur des .            */
                                        /*                  . de  serveurs .              . de  serveurs .  FLOTTANTs   .            */
                                        /*                  .              .              .              .              .            */
                                        /*                  .              .                                            .            */
                                        /*                  .              . taille de la memoire virtuelle par serveur .            */
                                        /*                  .              .                                            .            */
                                        /*                                                                                           */
                                        /*                         #              =              #              =                    */
                                        /*                            #           =           #                 =                    */
                                        /*                               #        =        #                    =                    */
                                        /*                                  #     =     #                       =                    */
                                        /*                                     #  =  #                          =                    */
                                        /*                                        #                             =                    */
                                        /*                                     #  =  #                          =                    */
                                        /*                                  #     =     #                       =                    */
                                        /*                               #        =        #                    =                    */
                                        /*                            #           =           #                 =                    */
                                        /*                         #              =              #              =                    */
                                        /*                                                                                           */
                                        /*                   -----------------------------------------------------------             */
                                        /*                  |              |              |              |              |            */
                                        /* adresse absolue  |    poids     |    poids     |    numero    |    poids     |            */
                                        /*   entrelacee     |    moyens    |    forts     |   de  page   |   faibles    |            */
                                        /*                  |              |              |              |              |            */
                                        /*                   -----------------------------------------------------------             */
                                        /*                  .              .              .              .              .            */
                                        /*                  .              .              .              .              .            */
                                        /*                  .    nombre    .              .   nombre     . longueur des .            */
                                        /*                  . de  serveurs .              . de  serveurs .  FLOTTANTs   .            */
                                        /*                  .              .              .              .              .            */
                                        /*                  .              .                                            .            */
                                        /*                  .              . taille de la memoire virtuelle par serveur .            */
                                        /*                  .              .                                            .            */
                                        /*                                                                                           */
          return(adresse_entrelacee);
          }

/*************************************************************************************************************************************/
/*                                                                                                                                   */
/*        C O D E   D E S   S E R V E U R S  :                                                                                       */
/*                                                                                                                                   */
/*************************************************************************************************************************************/
serveur()
          {
          if        (nombre_total_de_clients > RIEN)
                    {
                    if        (    (    (taille_de_la_memoire_virtuelle_par_serveur >= iLONGUEUR_caractere)
                                   &&   (taille_de_la_memoire_virtuelle_par_serveur >= iLONGUEUR_entier)
                                   &&   (taille_de_la_memoire_virtuelle_par_serveur >= iLONGUEUR_flottant)
                                   &&   (taille_de_la_memoire_virtuelle_par_serveur >= unite_d_entrelacage)
                                    )
                              &&   (    ((taille_de_la_memoire_virtuelle_par_serveur % iLONGUEUR_caractere) == RIEN)
                                   &&   ((taille_de_la_memoire_virtuelle_par_serveur % iLONGUEUR_entier) == RIEN)
                                   &&   ((taille_de_la_memoire_virtuelle_par_serveur % iLONGUEUR_flottant) == RIEN)
                                   &&   ((taille_de_la_memoire_virtuelle_par_serveur % unite_d_entrelacage) == RIEN)
                                    )
                               )
                              {
                              int       nombre_de_clients_enregistres=CLEAR;
                                        /* Pour compter les clients qui se sont enregistres...                                       */
                              int       octet_courant;
                              static    CHAR      *memoire_virtuelle;
                              Malloc(memoire_virtuelle,taille_de_la_memoire_virtuelle_par_serveur);
                                        /* Allocation de la memoire virtuelle dans chaque serveur.                                   */

                              for       (octet_courant=(ADRESSE_RELATIVE_0) ;
                                         octet_courant<(ADRESSE_RELATIVE_0+taille_de_la_memoire_virtuelle_par_serveur) ;
                                         octet_courant++
                                         )
                                        {
                                        *(memoire_virtuelle+octet_courant) = CLEAR;
                                        /* Nettoyage initial non optimise (octet par octet) de la memoire virtuelle...               */
                                        }

                              while     (nombre_total_de_clients > RIEN)
                                        {
                                        fonctions  fonction;
                                        Read(ANY,&fonction,iLONGUEUR_FONCTIONS);
                                        /* Recuperation de la fonction demandee par 'processeur_attendu' :                           */

                                        switch((int)fonction.code_fonction)
                                                  {
                                                  case      DEBUT:
                                                            {
                                                            Write(processeur_attendu
                                                                 ,&fonction
                                                                 ,iLONGUEUR_FONCTIONS
                                                                  );
                                        /* Et on renvoie tout simplement la fonction...                                              */
                                                            nombre_de_clients_enregistres++;
                                        /* On compte le nombre de processeurs enregistres. On notera qu'il est impossible de         */
                                        /* verifier simplement que 'nombre_de_clients_enregistres' atteint bien sa valeur maximale   */
                                        /* (c'est-a-dire 'nombre_total_de_clients'), car en effet, les demandes 'DEBUT' d'un certain */
                                        /* client peuvent s'imbriquer avec les 'STORE' et 'LOAD' des autres, auquel cas les tests    */
                                        /* que l'on pourrait faire alors ne seraient pas definitifs, et donneraient donc des         */
                                        /* messages d'erreurs temporaires et non justifies...                                        */
                                                            break;
                                                            }
                                                  case      FIN:
                                                            {
                                                            nombre_total_de_clients--;
                                        /* On decremente le nombre de processeurs potentiels...                                      */
                                                            break;
                                                            }
                                                  case      STORE:
                                                            {
                                                            Read(processeur_attendu
                                                                ,memoire_virtuelle+fonction.adresse_relative
                                                                ,fonction.longueur
                                                                 );
                                        /* Rangement dans la memoire virtuelle de la valeur demandee...                              */
                                                            break;
                                                            }
                                                  case      LOAD:
                                                            {
                                                            Write(processeur_attendu
                                                                 ,memoire_virtuelle+fonction.adresse_relative
                                                                 ,fonction.longueur
                                                                  );
                                        /* Transmission de la valeur demandee...                                                     */
                                                            break;
                                                            }
                                                  case      SWAP:
                                                            {
                                                            Write(processeur_attendu
                                                                 ,memoire_virtuelle+fonction.adresse_relative
                                                                 ,fonction.longueur
                                                                  );
                                                            Read(processeur_attendu
                                                                ,memoire_virtuelle+fonction.adresse_relative
                                                                ,fonction.longueur
                                                                 );
                                        /* Echange de la valeur demandee...                                                          */
                                                            break;
                                                            }
                                                  default:
                                                            {
                                                            fprintf(stderr
                                                                   ,"\n fonction non reconnue (code=%d)"
                                                                   ,(int)fonction.code_fonction
                                                                    );
                                                            break;
                                                            }
                                                  }
                                        }
                                        /* Fin d'activite du serveur...                                                              */

                              free(memoire_virtuelle);
                                        /* Desallocation de la memoire virtuelle dans chaque serveur.                                */
                              }
                    else
                              {
                              fprintf(stderr,"\n la taille de la memoire virtuelle n'est pas adaptee aux structures manipulees");
                              fprintf(stderr,"\n chaque serveur supporte %x octets",taille_de_la_memoire_virtuelle_par_serveur);
                              }
                    }
          else
                    {
                    fprintf(stderr,"\n il faut au moins %d processeurs (1)",PROCESSEURS);
                    fprintf(stderr,"\n ATTENTION, il est impossible de passer par ici");
                                        /* ATTENTION, il est impossible de passer par ici a cause de la validation faite dans        */
                                        /* 'main()' au sujet de 'nombre_total_processeurs'...                                        */
                    }

          return(OK);
          }

/*************************************************************************************************************************************/
/*                                                                                                                                   */
/*        P R O G R A M M E   P R I N C I P A L  :                                                                                   */
/*                                                                                                                                   */
/*************************************************************************************************************************************/
main()
          {

/*************************************************************************************************************************************/
/*                                                                                                                                   */
/*        R E C U P E R A T I O N   D E   L A   C O N F I G U R A T I O N   D E   " R U N "  :                                       */
/*                                                                                                                                   */
/*************************************************************************************************************************************/
          whoami(&processeur_local,&nproc,&nhost,&dimension);
          nombre_total_processeurs = PUISSANCE2(dimension);
          nombre_total_de_serveurs = nombre_total_processeurs/PROCESSEURS;
          nombre_total_de_clients = nombre_total_processeurs - nombre_total_de_serveurs;
                                        /* Recuperation de la configuration locale allouee.                                          */
          taille_de_la_memoire_virtuelle = TAILLE_DE_LA_MEMOIRE_VIRTUELLE;
                                        /* Taille totale de la memoire virtuelle.                                                    */
          if        (nombre_total_processeurs >= PROCESSEURS)
                    {
                    taille_de_la_memoire_virtuelle_par_serveur = taille_de_la_memoire_virtuelle / nombre_total_de_serveurs;
                                        /* Taille de la memoire virtuelle supportee par chaque serveur.                              */
                    if        ((taille_de_la_memoire_virtuelle % nombre_total_de_serveurs) == RIEN)
                              {
                              int       processeur;
                              Malloc(mapping_des_processeurs,nombre_total_processeurs*iLONGUEUR_entier);
                              Malloc(mapping_inverse_des_processeurs,nombre_total_processeurs*iLONGUEUR_entier);
                                        /* Allocation de la memoire virtuelle dans chaque serveur.                                   */
                              for       (processeur=(PREMIER_PROCESSEUR) ;
                                         processeur<(PREMIER_PROCESSEUR+nombre_total_processeurs) ;
                                         processeur++
                                         )
                                        {
                                        int       processeurL=processeur;
                                        int       processeurP=processeur;
                                        /* A priori, on initialise sur un "mapping" neutre (1 pour 1) pour la memoire virtuelle...   */

                                        if        (il_faut_mapper == OK)
                                                  {
                                                  if        (EST_SERVEUR(processeur))
                                                            {
                                                            processeurP=PREMIER_PROCESSEUR
                                                                       +(nombre_total_processeurs-UNITE)
                                                                       -((processeur-PREMIER_PROCESSEUR)+UNITE);
                                        /* Cette definition inverse l'ordre des serveurs...                                          */
                                                            }
                                                  else
                                                            {
                                                            processeurP=PREMIER_PROCESSEUR
                                                                       +(nombre_total_processeurs-UNITE)
                                                                       -((processeur-PREMIER_PROCESSEUR)-UNITE);
                                        /* Cette definition inverse l'ordre des clients...                                           */
                                                            }
                                                  }
                                        else
                                                  {
                                                  }

                                        *(mapping_des_processeurs+(processeurL-PREMIER_PROCESSEUR)) = processeurP;
                                        *(mapping_inverse_des_processeurs+(processeurP-PREMIER_PROCESSEUR)) = processeurL;
                                        }

/*************************************************************************************************************************************/
/*                                                                                                                                   */
/*        C O M M U N I C A T I O N  :                                                                                               */
/*                                                                                                                                   */
/*************************************************************************************************************************************/
                              if        (EST_SERVEUR(MAPPING(processeur_local)))
                                        {
                                        action_de_debut_pour_les_serveurs;
                                        /* Action de debut...                                                                        */

                                        serveur();
                                        /* Code specifique des serveurs.                                                             */

                                        action_de_fin_pour_les_serveurs;
                                        /* Action de fin...                                                                          */
                                        }
                              else
                                        {
                                        action_de_debut_pour_les_clients;
                                        /* Action de debut...                                                                        */

                                        client();
                                        /* Code specifique des clients.                                                              */

                                        action_de_fin_pour_les_clients;
                                        /* Action de fin...                                                                          */
                                        }

/*************************************************************************************************************************************/
/*                                                                                                                                   */
/*        F I N   D E S   T R A I T E M E N T S  :                                                                                   */
/*                                                                                                                                   */
/*************************************************************************************************************************************/
                              free(mapping_inverse_des_processeurs);
                              free(mapping_des_processeurs);
                              }
                    else
                              {
                              fprintf(stderr,"\n la taille de la memoire virtuelle est mauvaise");
                              }
                    }
          else
                    {
                    fprintf(stderr,"\n il faut au moins %d processeurs (2)",PROCESSEURS);
                    }
          exit();
          }




Copyright © Jean-François Colonna, 1997-2023.
Copyright © France Telecom R&D and CMAP (Centre de Mathématiques APpliquées) UMR CNRS 7641 / École polytechnique, Institut Polytechnique de Paris, 1997-2023.