version 1.33, 2010/08/22 16:38:36
|
version 1.35, 2010/08/25 09:06:49
|
Line 1726 deverrouillage_gestionnaire_signaux()
|
Line 1726 deverrouillage_gestionnaire_signaux()
|
|
|
#ifdef _BROKEN_SIGINFO |
#ifdef _BROKEN_SIGINFO |
|
|
// Remplacer les mutexes par des sémaphores SysV |
|
|
|
#define longueur_queue 256 |
#define longueur_queue 256 |
#define nombre_queues 13 |
#define nombre_queues 13 |
|
|
static int *fifos; |
static int *fifos; |
|
static int markov; |
static int segment; |
static int segment; |
static sem_t *semaphores[nombre_queues]; |
static sem_t *semaphores[nombre_queues]; |
static sem_t *semaphore_global; |
static sem_t *semaphore_global; |
Line 1826 creation_fifos_signaux(struct_processus
|
Line 1825 creation_fifos_signaux(struct_processus
|
* SIGSTART, SIGINJECT, SIGABORT, SIGFABORT |
* SIGSTART, SIGINJECT, SIGABORT, SIGFABORT |
*/ |
*/ |
|
|
|
int i; |
|
|
|
unsigned char *nom; |
|
|
# ifndef IPCS_SYSV // POSIX |
# ifndef IPCS_SYSV // POSIX |
|
|
|
if ((nom = nom_segment((*s_etat_processus).chemin_fichiers_temporaires, |
|
getpid())) == NULL) |
|
{ |
|
(*s_etat_processus).erreur_systeme = d_es_allocation_memoire; |
|
return; |
|
} |
|
|
|
if ((segment = shm_open(nom, O_RDWR | O_CREAT | O_EXCL, |
|
S_IRUSR | S_IWUSR)) == -1) |
|
{ |
|
free(nom); |
|
(*s_etat_processus).erreur_systeme = d_es_allocation_memoire; |
|
return; |
|
} |
|
|
|
if (ftruncate(segment, nombre_queues * ((2 * longueur_queue) + 4) * |
|
sizeof(int)) == -1) |
|
{ |
|
free(nom); |
|
(*s_etat_processus).erreur_systeme = d_es_allocation_memoire; |
|
return; |
|
} |
|
|
|
fifos = mmap(NULL, nombre_queues * ((2 * longueur_queue) + 4) * sizeof(int), |
|
PROT_READ | PROT_WRITE, MAP_SHARED, segment, 0); |
|
close(segment); |
|
|
|
if (((void *) fifos) == ((void *) -1)) |
|
{ |
|
if (shm_unlink(nom) == -1) |
|
{ |
|
free(nom); |
|
(*s_etat_processus).erreur_systeme = d_es_allocation_memoire; |
|
return; |
|
} |
|
|
|
free(nom); |
|
(*s_etat_processus).erreur_systeme = d_es_allocation_memoire; |
|
return; |
|
} |
|
|
|
free(nom); |
|
|
# else // SystemV |
# else // SystemV |
|
|
file *desc; |
file *desc; |
|
|
int i; |
|
|
|
key_t clef; |
key_t clef; |
|
|
unsigned char *nom; |
|
|
|
// Création d'un segment de données associé au PID du processus courant |
// Création d'un segment de données associé au PID du processus courant |
|
|
chemin = (*s_etat_processus).chemin_fichiers_temporaires; |
chemin = (*s_etat_processus).chemin_fichiers_temporaires; |
Line 1865 creation_fifos_signaux(struct_processus
|
Line 1908 creation_fifos_signaux(struct_processus
|
free(nom); |
free(nom); |
|
|
if ((segment = shmget(clef, |
if ((segment = shmget(clef, |
nombre_queues * (longueur_queue + 4) * sizeof(int), |
nombre_queues * ((2 * longueur_queue) + 4) * sizeof(int), |
IPC_CREAT | IPC_EXCL | S_IRUSR | S_IWUSR)) == -1) |
IPC_CREAT | IPC_EXCL | S_IRUSR | S_IWUSR)) == -1) |
{ |
{ |
(*s_etat_processus).erreur_systeme = d_es_allocation_memoire; |
(*s_etat_processus).erreur_systeme = d_es_allocation_memoire; |
Line 1895 creation_fifos_signaux(struct_processus
|
Line 1938 creation_fifos_signaux(struct_processus
|
* 2 : longueur de la queue (int) |
* 2 : longueur de la queue (int) |
* 3 : éléments restants (int) |
* 3 : éléments restants (int) |
* 4 à 4 + (2) : queue (int) |
* 4 à 4 + (2) : queue (int) |
|
* 4 + (2) + 1 ) 4 + 2 * (2) : horodatage en centième de secondes. |
*/ |
*/ |
|
|
for(i = 0; i < nombre_queues; i++) |
for(i = 0; i < nombre_queues; i++) |
Line 1947 creation_fifos_signaux(struct_processus
|
Line 1991 creation_fifos_signaux(struct_processus
|
|
|
free(nom); |
free(nom); |
|
|
|
markov = 0; |
|
|
return; |
return; |
} |
} |
|
|
Line 1955 liberation_fifos_signaux(struct_processu
|
Line 2001 liberation_fifos_signaux(struct_processu
|
{ |
{ |
int i; |
int i; |
|
|
|
# ifdef IPCS_SYSV // SystemV |
|
|
if (shmdt(fifos) == -1) |
if (shmdt(fifos) == -1) |
{ |
{ |
(*s_etat_processus).erreur_systeme = d_es_allocation_memoire; |
(*s_etat_processus).erreur_systeme = d_es_allocation_memoire; |
return; |
return; |
} |
} |
|
|
|
# else // POSIX |
|
|
|
if (munmap(fifos, nombre_queues * ((2 * longueur_queue) + 4) * sizeof(int)) |
|
!= 0) |
|
{ |
|
(*s_etat_processus).erreur_systeme = d_es_allocation_memoire; |
|
return; |
|
} |
|
|
|
# endif |
|
|
for(i = 0; i < nombre_queues; i++) |
for(i = 0; i < nombre_queues; i++) |
{ |
{ |
if (sem_close(semaphores[i]) != 0) |
if (sem_close(semaphores[i]) != 0) |
Line 1986 destruction_fifos_signaux(struct_process
|
Line 2045 destruction_fifos_signaux(struct_process
|
|
|
unsigned char *nom; |
unsigned char *nom; |
|
|
|
# ifdef IPCS_SYSV // SystemV |
|
|
if (shmdt(fifos) == -1) |
if (shmdt(fifos) == -1) |
{ |
{ |
(*s_etat_processus).erreur_systeme = d_es_allocation_memoire; |
(*s_etat_processus).erreur_systeme = d_es_allocation_memoire; |
Line 2008 destruction_fifos_signaux(struct_process
|
Line 2069 destruction_fifos_signaux(struct_process
|
unlink(nom); |
unlink(nom); |
free(nom); |
free(nom); |
|
|
|
# else // POSIX |
|
|
|
if (munmap(fifos, nombre_queues * ((2 * longueur_queue) + 4) * sizeof(int)) |
|
!= 0) |
|
{ |
|
(*s_etat_processus).erreur_systeme = d_es_allocation_memoire; |
|
return; |
|
} |
|
|
|
if ((nom = nom_segment(NULL, getpid())) == NULL) |
|
{ |
|
(*s_etat_processus).erreur_systeme = d_es_allocation_memoire; |
|
return; |
|
} |
|
|
|
if (shm_unlink(nom) != 0) |
|
{ |
|
free(nom); |
|
(*s_etat_processus).erreur_systeme = d_es_allocation_memoire; |
|
return; |
|
} |
|
|
|
free(nom); |
|
|
|
# endif |
|
|
for(i = 0; i < nombre_queues; i++) |
for(i = 0; i < nombre_queues; i++) |
{ |
{ |
if ((nom = nom_semaphore(getpid(), i)) == NULL) |
if ((nom = nom_semaphore(getpid(), i)) == NULL) |
Line 2042 destruction_fifos_signaux(struct_process
|
Line 2129 destruction_fifos_signaux(struct_process
|
return; |
return; |
} |
} |
|
|
int |
inline int |
queue_in(pid_t pid, int signal) |
horodatage() |
{ |
{ |
#undef printf |
int ts; |
// Transformer ce truc en POSIX ! On ne fait du SysV que si on n'a pas le choix |
|
|
|
# ifndef IPCS_SYSV |
struct timeval tv; |
# else // Traitement à l'aide d'IPCS SystemV |
|
|
gettimeofday(&tv, NULL); |
|
ts = (int) ((tv.tv_sec * 100) + (tv.tv_usec / 10000)); |
|
|
|
return(ts); |
|
} |
|
|
|
int |
|
queue_in(pid_t pid, int signal) |
|
{ |
|
int queue; |
int *base; |
int *base; |
int *buffer; |
int *buffer; |
int *projection_fifos; |
int horodatage_initial; |
int queue; |
|
int identifiant; |
int identifiant; |
|
int *projection_fifos; |
key_t clef; |
|
|
|
sem_t *semaphore; |
sem_t *semaphore; |
|
|
struct stat s_stat; |
queue = queue_de_signal(signal); |
|
|
unsigned char *nom; |
unsigned char *nom; |
|
|
queue = queue_de_signal(signal); |
# ifndef IPCS_SYSV |
|
|
|
// Ouverture des projections |
|
|
|
if ((nom = nom_segment(NULL, pid)) == NULL) |
|
{ |
|
return(-1); |
|
} |
|
|
|
// Dans le cas de SIGSTART, premier signal envoyé à un processus fils, |
|
// il convient d'attendre que le fichier support soit effectivement |
|
// accessible. Dans tous les autres cas, ce fichier doit exister. S'il |
|
// n'existe plus, le processus associé n'existe plus. |
|
|
|
if (signal == SIGSTART) |
|
{ |
|
horodatage_initial = horodatage(); |
|
|
|
while((identifiant = shm_open(nom, O_RDWR, S_IRUSR | S_IWUSR)) == -1) |
|
{ |
|
if (abs(horodatage_initial - horodatage()) > 500) |
|
{ |
|
return(-1); |
|
} |
|
} |
|
} |
|
else |
|
{ |
|
if ((identifiant = shm_open(nom, O_RDWR, S_IRUSR | S_IWUSR)) == -1) |
|
{ |
|
return(-1); |
|
} |
|
} |
|
|
|
projection_fifos = mmap(NULL, nombre_queues * ((2 * longueur_queue) + 4) |
|
* sizeof(int), PROT_READ | PROT_WRITE, MAP_SHARED, identifiant, 0); |
|
close(identifiant); |
|
|
|
if (((void *) projection_fifos) == ((void *) -1)) |
|
{ |
|
return(-1); |
|
} |
|
|
|
# else // Traitement à l'aide d'IPCS SystemV |
|
|
|
key_t clef; |
|
|
|
struct stat s_stat; |
|
|
// Ouverture des projections |
// Ouverture des projections |
|
|
Line 2083 queue_in(pid_t pid, int signal)
|
Line 2223 queue_in(pid_t pid, int signal)
|
{ |
{ |
// On attend que le fichier sois présent |
// On attend que le fichier sois présent |
|
|
while(stat(nom, &s_stat) != 0); |
horodatage_initial = horodatage(); |
|
|
|
while(stat(nom, &s_stat) != 0) |
|
{ |
|
if (abs(horodatage_initial - horodatage()) > 500) |
|
{ |
|
return(-1); |
|
} |
|
} |
} |
} |
|
|
if ((clef = ftok(nom, 1)) == -1) |
if ((clef = ftok(nom, 1)) == -1) |
Line 2096 queue_in(pid_t pid, int signal)
|
Line 2244 queue_in(pid_t pid, int signal)
|
if (signal == SIGSTART) |
if (signal == SIGSTART) |
{ |
{ |
while((identifiant = shmget(clef, |
while((identifiant = shmget(clef, |
nombre_queues * (longueur_queue + 4) * sizeof(int), |
nombre_queues * ((2 * longueur_queue) + 4) * sizeof(int), |
S_IRUSR | S_IWUSR)) == -1); |
S_IRUSR | S_IWUSR)) == -1); |
} |
} |
else |
else |
{ |
{ |
if ((identifiant = shmget(clef, |
if ((identifiant = shmget(clef, |
nombre_queues * (longueur_queue + 4) * sizeof(int), |
nombre_queues * ((2 * longueur_queue) + 4) * sizeof(int), |
S_IRUSR | S_IWUSR)) == -1) |
S_IRUSR | S_IWUSR)) == -1) |
{ |
{ |
return(-1); |
return(-1); |
Line 2116 queue_in(pid_t pid, int signal)
|
Line 2264 queue_in(pid_t pid, int signal)
|
return(-1); |
return(-1); |
} |
} |
|
|
|
# endif |
|
|
if ((nom = nom_semaphore(pid, queue)) == NULL) |
if ((nom = nom_semaphore(pid, queue)) == NULL) |
{ |
{ |
|
# ifdef IPCS_SYSV |
shmdt(projection_fifos); |
shmdt(projection_fifos); |
|
# else |
|
munmap(projection_fifos, nombre_queues * ((2 * longueur_queue) + 4) |
|
* sizeof(int)); |
|
# endif |
return(-1); |
return(-1); |
} |
} |
|
|
while((semaphore = sem_open(nom, 0)) == SEM_FAILED); |
while((semaphore = sem_open(nom, 0)) == SEM_FAILED); |
|
free(nom); |
|
|
if (sem_wait(semaphore) != 0) |
while(sem_wait(semaphore) != 0) |
{ |
{ |
shmdt(projection_fifos); |
if (errno != EINTR) |
return(-1); |
{ |
|
# ifdef IPCS_SYSV |
|
shmdt(projection_fifos); |
|
# else |
|
munmap(projection_fifos, nombre_queues * ((2 * longueur_queue) + 4) |
|
* sizeof(int)); |
|
# endif |
|
return(-1); |
|
} |
} |
} |
|
|
// Il ne faut pas empiler plusieurs SIGSTART car SIGSTART peut provenir |
|
// de l'instruction SWI. Plusieurs threads peuvent interrompre de façon |
|
// asynchrone le processus père durant une phase de signaux masqués. |
|
|
|
base = &(projection_fifos[(longueur_queue + 4) * queue]); |
base = &(projection_fifos[(longueur_queue + 4) * queue]); |
buffer = &(base[4]); |
buffer = &(base[4]); |
|
|
Line 2143 queue_in(pid_t pid, int signal)
|
Line 2303 queue_in(pid_t pid, int signal)
|
{ |
{ |
sem_post(semaphore); |
sem_post(semaphore); |
sem_close(semaphore); |
sem_close(semaphore); |
|
# ifdef IPCS_SYSV |
shmdt(projection_fifos); |
shmdt(projection_fifos); |
|
# else |
|
munmap(projection_fifos, nombre_queues * ((2 * longueur_queue) + 4) |
|
* sizeof(int)); |
|
# endif |
return(-1); |
return(-1); |
} |
} |
|
|
base[3]--; |
base[3]--; |
|
|
// base[1] contient le prochain élément à écrire |
// base[1] contient le prochain élément à écrire |
|
|
|
buffer[base[1] + (nombre_queues * base[2])] = horodatage(); |
buffer[base[1]++] = (int) pid; |
buffer[base[1]++] = (int) pid; |
base[1] %= base[2]; |
base[1] %= base[2]; |
|
|
if (sem_post(semaphore) != 0) |
if (sem_post(semaphore) != 0) |
{ |
{ |
|
# ifdef IPCS_SYSV |
shmdt(projection_fifos); |
shmdt(projection_fifos); |
|
# else |
|
munmap(projection_fifos, nombre_queues * ((2 * longueur_queue) + 4) |
|
* sizeof(int)); |
|
# endif |
sem_close(semaphore); |
sem_close(semaphore); |
return(-1); |
return(-1); |
} |
} |
Line 2163 queue_in(pid_t pid, int signal)
|
Line 2335 queue_in(pid_t pid, int signal)
|
sem_close(semaphore); |
sem_close(semaphore); |
|
|
// Fermeture des projections |
// Fermeture des projections |
|
# ifdef IPCS_SYSV |
shmdt(projection_fifos); |
shmdt(projection_fifos); |
|
# else |
|
munmap(projection_fifos, nombre_queues * ((2 * longueur_queue) + 4) |
|
* sizeof(int)); |
# endif |
# endif |
|
|
return(0); |
return(0); |
} |
} |
|
|
|
inline int |
|
chaine_markov(int markov, int delta) |
|
{ |
|
double memoire = 0.9; |
|
int valeur; |
|
|
|
valeur = (int) ((memoire * markov) + ((1 - memoire) * delta)); |
|
valeur = (valeur < 10) ? 10 : valeur; |
|
|
|
return(valeur); |
|
} |
|
|
pid_t |
pid_t |
origine_signal(int signal) |
origine_signal(int signal) |
{ |
{ |
|
logical1 drapeau; |
|
|
int *base; |
int *base; |
int *buffer; |
int *buffer; |
|
int delta; |
int pid; |
int pid; |
int queue; |
int queue; |
|
|
Line 2183 origine_signal(int signal)
|
Line 2373 origine_signal(int signal)
|
BUG(queue == -1, uprintf("[%d] Unknown signal %d in this context\n", |
BUG(queue == -1, uprintf("[%d] Unknown signal %d in this context\n", |
(int) getpid(), signal)); |
(int) getpid(), signal)); |
|
|
if (sem_wait(semaphores[queue]) != 0) |
while(sem_wait(semaphores[queue]) != 0) |
{ |
{ |
return(-1); |
if (errno != EINTR) |
|
{ |
|
return(-1); |
|
} |
} |
} |
|
|
// Le signal SIGCONT peut être envoyé de façon totalement asynchrone. |
// On retire les interruptions anciennes qui ont été ratées sauf s'il |
// Il peut y avoir plus de signaux envoyés que d'interruptions traitées. |
// s'agit de la dernière dans la queue. |
// Il convient donc de rectifier la queue lors du traitement de |
|
// l'interruption correspondante. Le gestionnaire étant installé sans |
base = &(fifos[(longueur_queue + 4) * queue]); |
// l'option NODEFER, la queue reste cohérente. |
buffer = &(base[4]); |
|
|
if (signal == SIGCONT) |
if (base[3] == (base[2] - 1)) |
{ |
|
base = &(fifos[(longueur_queue + 4) * queue]); |
|
buffer = &(base[4]); |
|
base[0] = (base[1] - 1) % base[2]; |
|
pid = buffer[base[0]++]; |
|
base[3] = base[2]; |
|
} |
|
else |
|
{ |
{ |
base = &(fifos[(longueur_queue + 4) * queue]); |
delta = abs(horodatage() - |
buffer = &(base[4]); |
buffer[base[0] + (nombre_queues * base[2])]); |
|
// Une seule interruption dans la queue. |
pid = buffer[base[0]++]; |
pid = buffer[base[0]++]; |
base[0] %= base[2]; |
base[0] %= base[2]; |
base[3]++; |
base[3]++; |
|
|
|
markov = chaine_markov(markov, delta); |
} |
} |
|
else if (base[3] >= base[2]) |
|
{ |
|
// Aucune interruption n'est dans la queue. |
|
// On a retiré trop d'interruptions de la queue. |
|
|
if (base[3] > base[2]) |
// (base[3] - base[2]) + 1 : nombre d'interruptions manquantes |
|
// base[0] - 1 : dernière interruption lue |
|
pid = buffer[((((base[0] + base[2] - 1) % base[2]) |
|
- ((base[3] - base[2]) + 1)) + base[2]) % base[2]]; |
|
} |
|
else |
{ |
{ |
sem_post(semaphores[queue]); |
// Plusieurs interruptions à distribuer. |
return(-1); |
drapeau = d_vrai; |
|
|
|
do |
|
{ |
|
delta = abs(horodatage() - |
|
buffer[base[0] + (nombre_queues * base[2])]); |
|
pid = buffer[base[0]++]; |
|
base[0] %= base[2]; |
|
base[3]++; |
|
|
|
if ((delta > (2 * markov)) && (base[3] < base[2])) |
|
{ |
|
drapeau = d_vrai; |
|
} |
|
else |
|
{ |
|
drapeau = d_faux; |
|
} |
|
} while(drapeau == d_vrai); |
|
|
|
markov = chaine_markov(markov, delta); |
} |
} |
|
|
if (sem_post(semaphores[queue]) != 0) |
if (sem_post(semaphores[queue]) != 0) |
Line 2227 origine_signal(int signal)
|
Line 2444 origine_signal(int signal)
|
|
|
#endif |
#endif |
|
|
#ifdef printf |
|
# undef printf |
|
#endif |
|
|
|
void |
void |
interruption1(SIGHANDLER_ARGS) |
interruption1(SIGHANDLER_ARGS) |
{ |
{ |
Line 2987 kill_broken_siginfo(pid_t pid, int signa
|
Line 3200 kill_broken_siginfo(pid_t pid, int signa
|
return(-1); |
return(-1); |
} |
} |
|
|
if ((semaphore = sem_open(nom, 0)) == SEM_FAILED) |
while((semaphore = sem_open(nom, 0)) == SEM_FAILED); |
{ |
|
free(nom); |
|
return(-1); |
|
} |
|
|
|
free(nom); |
free(nom); |
|
|
if (sem_wait(semaphore) == -1) |
while(sem_wait(semaphore) != 0) |
{ |
{ |
return(-1); |
if (errno != EINTR) |
|
{ |
|
return(-1); |
|
} |
} |
} |
|
|
if ((signal != 0) && (signal != SIGINT)) |
if ((signal != 0) && (signal != SIGINT)) |
Line 3034 pthread_kill_broken_siginfo(pthread_t ti
|
Line 3245 pthread_kill_broken_siginfo(pthread_t ti
|
return(-1); |
return(-1); |
} |
} |
|
|
if ((semaphore = sem_open(nom, 0)) == SEM_FAILED) |
while((semaphore = sem_open(nom, 0)) == SEM_FAILED); |
{ |
|
free(nom); |
|
return(-1); |
|
} |
|
|
|
free(nom); |
free(nom); |
|
|
if (sem_wait(semaphore) == -1) |
while(sem_wait(semaphore) != 0) |
{ |
{ |
return(-1); |
if (errno != EINTR) |
|
{ |
|
return(-1); |
|
} |
} |
} |
|
|
if ((signal != 0) && (signal != SIGINT)) |
if ((signal != 0) && (signal != SIGINT)) |