MAM_Zombies.c 3.12 KB
Newer Older
iker_martin's avatar
iker_martin committed
1
2
3
4
5
6
7
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <mpi.h>
#include <signal.h>
8
9
#include "MAM_Zombies.h"
#include "MAM_DataStructures.h"
iker_martin's avatar
iker_martin committed
10
11

#define PIDS_QTY 320
12
13
14
//TODO Add option to allow the usage of signal USR2 or not.
//This code asumes ROOT of each group will be the last to be zombified
//
iker_martin's avatar
iker_martin committed
15

16
17
18
19
20
void MAM_I_zombies_collect(int new_zombies);
void MAM_I_zombies_split();
void MAM_I_zombies_suspend();
int MAM_I_zombies_awake();
void zombies_handler_usr2() {}
iker_martin's avatar
iker_martin committed
21

22
23
int *pids = NULL;
int zombies_qty = 0;
iker_martin's avatar
iker_martin committed
24
25


26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
void MAM_Zombies_service_init() {
  zombies_qty = 0;
  pids = malloc(PIDS_QTY * sizeof(int));

  for(int i=0; i<PIDS_QTY; i++) {
    pids[i] = 0;
  }
}

int MAM_Zombies_service_free() {
  int request_abort = MAM_I_zombies_awake();
  free(pids);
  return request_abort;
}


void MAM_Zombies_update() {
  int myId, numP, new_zombies;

  MPI_Comm_rank(mall->original_comm, &myId);
  MPI_Comm_size(mall->original_comm, &numP);
iker_martin's avatar
iker_martin committed
47

48
49
50
51
52
  MPI_Allreduce(&mall->zombie, &new_zombies, 1, MPI_INT, MPI_SUM, mall->original_comm);
  if(new_zombies && new_zombies < numP) {
    MAM_I_zombies_collect(new_zombies);
    MAM_I_zombies_split();
    MAM_I_zombies_suspend();
53
    if(myId == MAM_ROOT) zombies_qty += new_zombies;
54
55
56
57
  }
}

void MAM_I_zombies_collect(int new_zombies) {
iker_martin's avatar
iker_martin committed
58
  int pid = getpid();
59
60
61
62
63
64
65
66
  int *pids_counts, *pids_displs;
  int i, count, active;
  int myId, numP;

  MPI_Comm_rank(mall->original_comm, &myId);
  MPI_Comm_size(mall->original_comm, &numP);
  pids_counts = (int *) malloc(numP * sizeof(int));
  pids_displs = (int *) malloc(numP * sizeof(int));
iker_martin's avatar
iker_martin committed
67

68
  #if USE_MAL_DEBUG > 2
69
    if(myId == MAM_ROOT){ DEBUG_FUNC("Collecting zombies", mall->myId, mall->numP); } fflush(stdout);
70
71
  #endif

72
  count = mall->zombie;
73
  if(myId == MAM_ROOT) {
74
75
76
77
78
79
80
81
82
    active = numP - new_zombies;
    for(i=0; i < active; i++) {
      pids_counts[i] = 0;
    }
    pids_displs[i-1] = -1;
    for(; i< active+new_zombies; i++) {
      pids_counts[i] = 1;
      pids_displs[i] = (pids_displs[i-1] + 1) + zombies_qty;
    }
iker_martin's avatar
iker_martin committed
83
  }
84
  MPI_Gatherv(&pid, count, MPI_INT, pids, pids_counts, pids_displs, MPI_INT, MAM_ROOT, mall->original_comm);
iker_martin's avatar
iker_martin committed
85
86
87
88
  free(pids_counts);
  free(pids_displs);
}

89
90
91
void MAM_I_zombies_split() {
  int myId, color;
  MPI_Comm new_original_comm;
iker_martin's avatar
iker_martin committed
92

93
94
95
  MPI_Comm_rank(mall->original_comm, &myId);
  color = mall->zombie ? MPI_UNDEFINED : 1;
  MPI_Comm_split(mall->original_comm, color, myId, &new_original_comm);
iker_martin's avatar
iker_martin committed
96

97
  if(mall->original_comm != MPI_COMM_WORLD) MPI_Comm_free(&mall->original_comm);
98
  if(new_original_comm != MPI_COMM_NULL) MPI_Comm_set_name(new_original_comm, "MAM_ORIGINAL");
99
  mall->original_comm = new_original_comm;
iker_martin's avatar
iker_martin committed
100
101
}

102
void MAM_I_zombies_suspend() {
iker_martin's avatar
iker_martin committed
103
  struct sigaction act;
104
  if(!mall->zombie) return;
iker_martin's avatar
iker_martin committed
105
106
107

  sigemptyset(&act.sa_mask);
  act.sa_flags=0;
108
  act.sa_handler=zombies_handler_usr2;
iker_martin's avatar
iker_martin committed
109
110
111
112
113
114
115
116
117

  sigaction(SIGUSR2, &act, NULL);

  sigset_t set;
  sigprocmask(SIG_SETMASK,NULL,&set);

  sigsuspend(&set);
}

118
119
120
int MAM_I_zombies_awake() {
  if(mall->internode_group && zombies_qty) return 1; //Request Abort
  for(int i=0; i < zombies_qty; i++) { // Despertar a los zombies
iker_martin's avatar
iker_martin committed
121
122
    kill(pids[i], SIGUSR2);
  }
123
124
  zombies_qty = 0;
  return 0; //Normal termination
iker_martin's avatar
iker_martin committed
125
}