コード例 #1
0
ファイル: minor_gc.c プロジェクト: ocamllabs/ocaml-multicore
void caml_empty_minor_heap_domain (struct domain* domain)
{
  CAMLnoalloc;
  caml_domain_state* domain_state = domain->state;
  struct caml_minor_tables *minor_tables = domain_state->minor_tables;
  unsigned rewrite_successes = 0;
  unsigned rewrite_failures = 0;
  char* young_ptr = domain_state->young_ptr;
  char* young_end = domain_state->young_end;
  uintnat minor_allocated_bytes = young_end - young_ptr;
  struct oldify_state st = {0};
  value **r;
  struct caml_ephe_ref_elt *re;
  struct caml_custom_elt *elt;

  st.promote_domain = domain;

  if (minor_allocated_bytes != 0) {
    uintnat prev_alloc_words = domain_state->allocated_words;

#ifdef DEBUG
    /* In DEBUG mode, verify that the minor_ref table contains all young-young pointers
       from older to younger objects */
    {
    struct addrmap young_young_ptrs = ADDRMAP_INIT;
    mlsize_t i;
    value iter;
    for (r = minor_tables->minor_ref.base; r < minor_tables->minor_ref.ptr; r++) {
      *caml_addrmap_insert_pos(&young_young_ptrs, (value)*r) = 1;
    }
    for (iter = (value)young_ptr;
         iter < (value)young_end;
         iter = next_minor_block(domain_state, iter)) {
      value hd = Hd_hp(iter);
      if (hd != 0) {
        value curr = Val_hp(iter);
        tag_t tag = Tag_hd (hd);

        if (tag < No_scan_tag && tag != Cont_tag) {
          // FIXME: should scan Cont_tag
          for (i = 0; i < Wosize_hd(hd); i++) {
            value* f = Op_val(curr) + i;
            if (Is_block(*f) && is_in_interval(*f, young_ptr, young_end) &&
                *f < curr) {
              CAMLassert(caml_addrmap_contains(&young_young_ptrs, (value)f));
            }
          }
        }
      }
    }
    caml_addrmap_clear(&young_young_ptrs);
    }
#endif

    caml_gc_log ("Minor collection of domain %d starting", domain->state->id);
    caml_ev_begin("minor_gc");
    caml_ev_begin("minor_gc/roots");
    caml_do_local_roots(&oldify_one, &st, domain, 0);

    caml_scan_stack(&oldify_one, &st, domain_state->current_stack);

    for (r = minor_tables->major_ref.base; r < minor_tables->major_ref.ptr; r++) {
      value x = **r;
      oldify_one (&st, x, &x);
    }
    caml_ev_end("minor_gc/roots");

    caml_ev_begin("minor_gc/promote");
    oldify_mopup (&st);
    caml_ev_end("minor_gc/promote");

    caml_ev_begin("minor_gc/ephemerons");
    for (re = minor_tables->ephe_ref.base;
         re < minor_tables->ephe_ref.ptr; re++) {
      CAMLassert (Ephe_domain(re->ephe) == domain);
      if (re->offset == CAML_EPHE_DATA_OFFSET) {
        /* Data field has already been handled in oldify_mopup. Handle only
         * keys here. */
        continue;
      }
      value* key = &Op_val(re->ephe)[re->offset];
      if (*key != caml_ephe_none && Is_block(*key) &&
          is_in_interval(*key, young_ptr, young_end)) {
        resolve_infix_val(key);
        if (Hd_val(*key) == 0) { /* value copied to major heap */
          *key = Op_val(*key)[0];
        } else {
          CAMLassert(!ephe_check_alive_data(re,young_ptr,young_end));
          *key = caml_ephe_none;
          Ephe_data(re->ephe) = caml_ephe_none;
        }
      }
    }
    caml_ev_end("minor_gc/ephemerons");

    caml_ev_begin("minor_gc/update_minor_tables");
    for (r = minor_tables->major_ref.base;
         r < minor_tables->major_ref.ptr; r++) {
      value v = **r;
      if (Is_block (v) && is_in_interval ((value)Hp_val(v), young_ptr, young_end)) {
        value vnew;
        header_t hd = Hd_val(v);
        int offset = 0;
        if (Tag_hd(hd) == Infix_tag) {
          offset = Infix_offset_hd(hd);
          v -= offset;
        }
        CAMLassert (Hd_val(v) == 0);
        vnew = Op_val(v)[0] + offset;
        CAMLassert (Is_block(vnew) && !Is_minor(vnew));
        CAMLassert (Hd_val(vnew));
        if (Tag_hd(hd) == Infix_tag) {
          CAMLassert(Tag_val(vnew) == Infix_tag);
          v += offset;
        }
        if (caml_domain_alone()) {
          **r = vnew;
          ++rewrite_successes;
        } else {
          if (atomic_compare_exchange_strong((atomic_value*)*r, &v, vnew))
            ++rewrite_successes;
          else
            ++rewrite_failures;
        }
      }
    }
    CAMLassert (!caml_domain_alone() || rewrite_failures == 0);
    caml_ev_end("minor_gc/update_minor_tables");

    caml_ev_begin("minor_gc/finalisers");
    caml_final_update_last_minor(domain);
    /* Run custom block finalisation of dead minor values */
    for (elt = minor_tables->custom.base; elt < minor_tables->custom.ptr; elt++) {
      value v = elt->block;
      if (Hd_val(v) == 0) {
        /* !!caml_adjust_gc_speed(elt->mem, elt->max); */
      } else {
        /* Block will be freed: call finalisation function, if any */
        void (*final_fun)(value) = Custom_ops_val(v)->finalize;
        if (final_fun != NULL) final_fun(v);
      }
    }
    caml_final_empty_young(domain);
    caml_ev_end("minor_gc/finalisers");


    clear_table ((struct generic_table *)&minor_tables->major_ref);
    clear_table ((struct generic_table *)&minor_tables->minor_ref);
    clear_table ((struct generic_table *)&minor_tables->ephe_ref);
    clear_table ((struct generic_table *)&minor_tables->custom);

    domain_state->young_ptr = domain_state->young_end;
    domain_state->stat_minor_words += Wsize_bsize (minor_allocated_bytes);
    domain_state->stat_minor_collections++;
    domain_state->stat_promoted_words += domain_state->allocated_words - prev_alloc_words;

    caml_ev_end("minor_gc");
    caml_gc_log ("Minor collection of domain %d completed: %2.0f%% of %u KB live, rewrite: successes=%u failures=%u",
                 domain->state->id,
                 100.0 * (double)st.live_bytes / (double)minor_allocated_bytes,
                 (unsigned)(minor_allocated_bytes + 512)/1024, rewrite_successes, rewrite_failures);
  }
  else {
    caml_final_empty_young(domain);
    caml_gc_log ("Minor collection of domain %d: skipping", domain->state->id);
  }

#ifdef DEBUG
  {
    value *p;
    for (p = (value *) domain_state->young_start;
         p < (value *) domain_state->young_end; ++p){
      *p = Debug_free_minor;
    }
  }
#endif
}
コード例 #2
0
ファイル: minor_gc.c プロジェクト: ocamllabs/ocaml-multicore
CAMLexport value caml_promote(struct domain* domain, value root)
{
  value **r;
  value iter, f;
  mlsize_t i;
  caml_domain_state* domain_state = domain->state;
  struct caml_minor_tables *minor_tables = domain_state->minor_tables;
  char* young_ptr = domain_state->young_ptr;
  char* young_end = domain_state->young_end;
  float percent_to_scan;
  uintnat prev_alloc_words = domain_state->allocated_words;
  struct oldify_state st = {0};
  struct caml_ephe_ref_elt *re;

  /* Integers are already shared */
  if (Is_long(root))
    return root;

  /* Objects which are in the major heap are already shared. */
  if (!Is_minor(root))
    return root;

  st.oldest_promoted = (value)domain_state->young_start;
  st.promote_domain = domain;

  CAMLassert(caml_owner_of_young_block(root) == domain);
  oldify_one (&st, root, &root);
  oldify_mopup (&st);

  CAMLassert (!Is_minor(root));
  /* FIXME: surely a newly-allocated root is already darkened? */
  caml_darken(0, root, 0);

  percent_to_scan = st.oldest_promoted <= (value)young_ptr ? 0.0 :
    (((float)(st.oldest_promoted - (value)young_ptr)) * 100.0 /
     ((value)young_end - (value)domain_state->young_start));

  if (percent_to_scan > Percent_to_promote_with_GC) {
    caml_gc_log("caml_promote: forcing minor GC. %%_minor_to_scan=%f", percent_to_scan);
    // ???
    caml_empty_minor_heap_domain (domain);
  } else {
    caml_do_local_roots (&forward_pointer, st.promote_domain, domain, 1);
    caml_scan_stack (&forward_pointer, st.promote_domain, domain_state->current_stack);

    /* Scan major to young pointers. */
    for (r = minor_tables->major_ref.base;
         r < minor_tables->major_ref.ptr; r++) {
      value old_p = **r;
      if (Is_block(old_p) && is_in_interval(old_p,young_ptr,young_end)) {
        value new_p = old_p;
        forward_pointer (st.promote_domain, new_p, &new_p);
        if (old_p != new_p) {
          if (caml_domain_alone())
            **r = new_p;
          else
            atomic_compare_exchange_strong((atomic_value*)*r, &old_p, new_p);
        }
      }
    }

    /* Scan ephemeron ref table */
    for (re = minor_tables->ephe_ref.base;
         re < minor_tables->ephe_ref.ptr; re++) {
      value* key = &Op_val(re->ephe)[re->offset];
      if (Is_block(*key) && is_in_interval(*key,young_ptr,young_end)) {
        forward_pointer (st.promote_domain, *key, key);
      }
    }

    /* Scan young to young pointers */
    for (r = minor_tables->minor_ref.base; r < minor_tables->minor_ref.ptr; r++) {
      forward_pointer (st.promote_domain, **r, *r);
    }

    /* Scan newer objects */
    for (iter = (value)young_ptr;
         iter <= st.oldest_promoted;
         iter = next_minor_block(domain_state, iter)) {
      value hd = Hd_hp(iter);
      value curr = Val_hp(iter);
      if (hd != 0) {
        tag_t tag = Tag_hd (hd);
        if (tag == Cont_tag) {
          struct stack_info* stk = Ptr_val(Op_val(curr)[0]);
          if (stk != NULL)
            caml_scan_stack(&forward_pointer, st.promote_domain, stk);
        } else if (tag < No_scan_tag) {
          for (i = 0; i < Wosize_hd (hd); i++) {
            f = Op_val(curr)[i];
            if (Is_block(f)) {
              forward_pointer (st.promote_domain, f,((value*)curr) + i);
            }
          }
        }
      }
    }
  }
  domain_state->stat_promoted_words += domain_state->allocated_words - prev_alloc_words;
  return root;
}
コード例 #3
0
ファイル: minor_gc.c プロジェクト: ocamllabs/ocaml-multicore
/* Finish the work that was put off by [oldify_one].
   Note that [oldify_one] itself is called by oldify_mopup, so we
   have to be careful to remove the first entry from the list before
   oldifying its fields. */
static void oldify_mopup (struct oldify_state* st)
{
  value v, new_v, f;
  mlsize_t i;
  caml_domain_state* domain_state =
    st->promote_domain ? st->promote_domain->state : Caml_state;
  struct caml_ephe_ref_table ephe_ref_table = domain_state->minor_tables->ephe_ref;
  struct caml_ephe_ref_elt *re;
  char* young_ptr = domain_state->young_ptr;
  char* young_end = domain_state->young_end;
  int redo = 0;

  while (st->todo_list != 0) {
    v = st->todo_list;                 /* Get the head. */
    CAMLassert (Hd_val (v) == 0);             /* It must be forwarded. */
    new_v = Op_val (v)[0];                /* Follow forward pointer. */
    st->todo_list = Op_val (new_v)[1]; /* Remove from list. */

    f = Op_val (new_v)[0];
    CAMLassert (!Is_debug_tag(f));
    if (Is_block (f) &&
        is_in_interval((value)Hp_val(v), young_ptr, young_end)) {
      oldify_one (st, f, Op_val (new_v));
    }
    for (i = 1; i < Wosize_val (new_v); i++){
      f = Op_val (v)[i];
      CAMLassert (!Is_debug_tag(f));
      if (Is_block (f) &&
          is_in_interval((value)Hp_val(v), young_ptr, young_end)) {
        oldify_one (st, f, Op_val (new_v) + i);
      } else {
        Op_val (new_v)[i] = f;
      }
    }
    CAMLassert (Wosize_val(new_v));
  }

  /* Oldify the data in the minor heap of alive ephemeron
     During minor collection keys outside the minor heap are considered alive */
  for (re = ephe_ref_table.base;
       re < ephe_ref_table.ptr; re++) {
    /* look only at ephemeron with data in the minor heap */
    if (re->offset == CAML_EPHE_DATA_OFFSET) {
      value *data = &Ephe_data(re->ephe);
      if (*data != caml_ephe_none && Is_block(*data) &&
          is_in_interval(*data, young_ptr, young_end)) {
        resolve_infix_val(data);
        if (Hd_val(*data) == 0) { /* Value copied to major heap */
          *data = Op_val(*data)[0];
        } else {
          if (ephe_check_alive_data(re, young_ptr, young_end)) {
            oldify_one(st, *data, data);
            redo = 1; /* oldify_todo_list can still be 0 */
          }
        }
      }
    }
  }

  if (redo) oldify_mopup (st);
}
コード例 #4
0
ファイル: minor_gc.c プロジェクト: ocamllabs/ocaml-multicore
/* Note that the tests on the tag depend on the fact that Infix_tag,
   Forward_tag, and No_scan_tag are contiguous. */
static void oldify_one (void* st_v, value v, value *p)
{
  struct oldify_state* st = st_v;
  value result;
  header_t hd;
  mlsize_t sz, i;
  mlsize_t infix_offset;
  tag_t tag;
  caml_domain_state* domain_state =
    st->promote_domain ? st->promote_domain->state : Caml_state;
  char* young_ptr = domain_state->young_ptr;
  char* young_end = domain_state->young_end;
  CAMLassert (domain_state->young_start <= domain_state->young_ptr &&
          domain_state->young_ptr <= domain_state->young_end);

 tail_call:
  if (!(Is_block(v) && is_in_interval((value)Hp_val(v), young_ptr, young_end))) {
    /* not a minor block */
    *p = v;
    return;
  }

  infix_offset = 0;
  do {
    hd = Hd_val (v);
    if (hd == 0) {
      /* already forwarded, forward pointer is first field. */
      *p = Op_val(v)[0] + infix_offset;
      return;
    }
    tag = Tag_hd (hd);
    if (tag == Infix_tag) {
      /* Infix header, retry with the real block */
      CAMLassert (infix_offset == 0);
      infix_offset = Infix_offset_hd (hd);
      CAMLassert(infix_offset > 0);
      v -= infix_offset;
    }
  } while (tag == Infix_tag);

  if (((value)Hp_val(v)) > st->oldest_promoted) {
    st->oldest_promoted = (value)Hp_val(v);
  }

  if (tag == Cont_tag) {
    struct stack_info* stk = Ptr_val(Op_val(v)[0]);
    CAMLassert(Wosize_hd(hd) == 1 && infix_offset == 0);
    result = alloc_shared(1, Cont_tag);
    *p = result;
    Op_val(result)[0] = Val_ptr(stk);
    *Hp_val (v) = 0;
    Op_val(v)[0] = result;
    if (stk != NULL)
      caml_scan_stack(&oldify_one, st, stk);
  } else if (tag < Infix_tag) {
    value field0;
    sz = Wosize_hd (hd);
    st->live_bytes += Bhsize_hd(hd);
    result = alloc_shared (sz, tag);
    *p = result + infix_offset;
    field0 = Op_val(v)[0];
    CAMLassert (!Is_debug_tag(field0));
    *Hp_val (v) = 0;           /* Set forward flag */
    Op_val(v)[0] = result;     /*  and forward pointer. */
    if (sz > 1){
      Op_val (result)[0] = field0;
      Op_val (result)[1] = st->todo_list;    /* Add this block */
      st->todo_list = v;                     /*  to the "to do" list. */
    }else{
      CAMLassert (sz == 1);
      p = Op_val(result);
      v = field0;
      goto tail_call;
    }
  } else if (tag >= No_scan_tag) {
    sz = Wosize_hd (hd);
    st->live_bytes += Bhsize_hd(hd);
    result = alloc_shared(sz, tag);
    for (i = 0; i < sz; i++) {
      value curr = Op_val(v)[i];
      Op_val (result)[i] = curr;
    }
    *Hp_val (v) = 0;           /* Set forward flag */
    Op_val (v)[0] = result;    /*  and forward pointer. */
    CAMLassert (infix_offset == 0);
    *p = result;
  } else {
    CAMLassert (tag == Forward_tag);
    CAMLassert (infix_offset == 0);

    value f = Forward_val (v);
    tag_t ft = 0;

    if (Is_block (f)) {
      ft = Tag_val (Hd_val (f) == 0 ? Op_val (f)[0] : f);
    }

    if (ft == Forward_tag || ft == Lazy_tag || ft == Double_tag) {
      /* Do not short-circuit the pointer.  Copy as a normal block. */
      CAMLassert (Wosize_hd (hd) == 1);
      st->live_bytes += Bhsize_hd(hd);
      result = alloc_shared (1, Forward_tag);
      *p = result;
      *Hp_val (v) = 0;             /* Set (GC) forward flag */
      Op_val (v)[0] = result;      /*  and forward pointer. */
      p = Op_val (result);
      v = f;
      goto tail_call;
    } else {
      v = f;                        /* Follow the forwarding */
      goto tail_call;               /*  then oldify. */
    }
  }
}
コード例 #5
0
ファイル: layer.c プロジェクト: marcopovitch/mesh
/*-----------------------------------------------------------------*/
void make_layer(struct layer_t *layer, struct mesh_t *mesh)
{

    struct cell_t *last_m = NULL;

    struct cell_t *first_m = NULL;

    struct cell_t *m = NULL;

    struct cell_t *c1, *c2, *first_cell;

    struct cell_t *cell2return = NULL;

    struct mesh_parameter_t *mp;

    int n, nb_meridian, nb_max_meridian, nl;

    float c1_lon;

    float plon;                 /* lon step */

    mp = mesh->parameter;

    layer->ncells = 0;
    nb_meridian = layer->nlon;
    nb_max_meridian = (int) (360. / (layer->lon_unit * mp->lon_unit_size));

    if (DEBUG)
        fprintf(stderr, "make_layer : nb meridians to make = %d\n",
                nb_meridian);

    n = 0;
    c1_lon = mp->lon_min;
    plon = mp->lon_unit_size * layer->lon_unit;

    while (n < nb_meridian) {
        m = make_meridian(layer, mesh);

        if (first_m == NULL) {
            first_m = m;
            if (is_in_interval(modulo360(mp->lon_min, 0), 0., 180. - plon)) {
                if (DEBUG)
                    fprintf(stderr, "make_layer : init cell in [0-180[\n");
                layer->cell = first_m;
            } else {
                if (DEBUG)
                    fprintf(stderr,
                            "make_layer : init cell in [180-360[\n");
                cell2return = first_m;
                while (cell2return->neighbour_list[NSD_1]) {
                    cell2return =
                        get_cell_from_list(cell2return->neighbour_list
                                           [NSD_1], 0);
                }
                layer->cell = cell2return;
            }

        } else {
            if (modulo360(c1_lon, 0) > 180. - EPS
                && modulo360(c1_lon, 0) < 180. + EPS) {
                if (DEBUG)
                    fprintf(stderr,
                            "make_layer : link_meridian_2 (%.1f-%.1f)\n",
                            c1_lon, c1_lon + plon);
                nl = link_meridian_2(last_m, m);
            } else if (modulo360(c1_lon, 1) > 360. - EPS
                       && modulo360(c1_lon, 1) < 360. + EPS) {
                if (DEBUG)
                    fprintf(stderr,
                            "make_layer : link_meridian_3 (%.1f-%.1f)\n",
                            c1_lon, c1_lon + plon);
                nl = link_meridian_3(last_m, m);
            } else {
                if (DEBUG)
                    fprintf(stderr,
                            "make_layer : link_meridian_1 (%.1f-%.1f)\n",
                            c1_lon, c1_lon + plon);
                nl = link_meridian_1(last_m, m);
            }
            if (DEBUG)
                fprintf(stderr, "make_layer : nb links made = %d\n", nl);
        }
        last_m = m;
        n++;
        c1_lon += plon;
    }

    /*----------------------------*/
    /* link last & first meridian */

    /*----------------------------*/
    if ((int) (mp->lon_max - mp->lon_min) == 360) {
        if (DEBUG)
            fprintf(stderr, "make_layer : link first and last meridian\n");
        if (is_in_interval
            (0., modulo360(c1_lon, 0) - EPS,
             modulo360(c1_lon + plon, 0) - EPS)) {
            if (DEBUG)
                fprintf(stderr,
                        "make_layer : link_meridian_3 (%.1f-%.1f)\n",
                        c1_lon, c1_lon + plon);
            link_meridian_3(last_m, first_m);
        } else
            if (is_in_interval
                (180., modulo360(c1_lon, 0) - EPS,
                 modulo360(c1_lon + plon, 1) - EPS)) {
            if (DEBUG)
                fprintf(stderr,
                        "make_layer : link_meridian_2 (%.1f-%.1f)\n",
                        c1_lon, c1_lon + plon);
            link_meridian_2(last_m, first_m);
        } else {
            if (DEBUG)
                fprintf(stderr,
                        "make_layer : link_meridian_1 (%.1f-%.1f)\n",
                        c1_lon, c1_lon + plon);
            link_meridian_1(last_m, first_m);
        }
    }

    /*return; */

    /*---------------------*/
    /* link South Pole ... */

    /*---------------------*/
    if ((int) (mp->lat_min) == -90) {
        if (DEBUG)
            fprintf(stderr, "make_layer : link south (topo)\n");

        if (cell2return) {
            c1 = first_cell = cell2return;
        } else {
            c1 = first_cell = first_m;
        }
        c1_lon = mp->lon_min;
        plon = mp->lon_unit_size * layer->lon_unit;

        /* dump couronne */
        /*if (DEBUG) {
           n = 0;
           fprintf(stderr, "\ncouronne = ");
           c2 = c1;
           while (n < nb_meridian) {
           n++;
           fprintf(stderr, "%p(%d), ", c2, n);
           c2 = get_cell_from_list(c2->neighbour_list[EAST_D], 0);
           }
           fprintf(stderr, "\n");
           } */

        nl = 0;                 /* number of move to complete the pole link */
        do {
            if (c1_lon + 180. < mp->lon_max - plon + EPS) {
                /* link is possible */

                /* we go on the cell to link with c1 */
                n = 0;
                c2 = c1;
                if (VERBOSE)
                    fprintf(stderr,
                            "make_layer : going to cell c2 to link with c1 : ");
                while (n < nb_max_meridian / 2) {       /*  nb_max_meridian must be = 2*k */
                    if (VERBOSE)
                        fprintf(stderr, "+");
                    c2 = get_cell_from_list(c2->neighbour_list[EAST_D], 0);
                    n++;
                }
                if (VERBOSE)
                    fprintf(stderr, "\n");

                /*if (DEBUG)
                   fprintf(stderr, "with c2 = %p\n", c2);
                 */

                /* the link */
                if (is_in_interval
                    (modulo360(c1_lon, 0), 0. - EPS, 180. - EPS)
                    && !is_in_interval(180., modulo360(c1_lon, 0) - EPS,
                                       modulo360(c1_lon + plon,
                                                 1) - EPS)) {
                    if (VERBOSE) {
                        fprintf(stderr, "make_layer : c1 is in [0,180[\n");
                        fprintf(stderr, "make_layer : c1=%p c2=%p\n", c1,
                                c2);
                        fprintf(stderr,
                                "make_layer : c1->nsd2 = %p, c2->nsd1 = %p\n",
                                get_cell_from_list(c1->neighbour_list
                                                   [NSD_2], 0),
                                get_cell_from_list(c2->neighbour_list
                                                   [NSD_1], 0));
                    }

                    c1->neighbour_list[NSD_2] =
                        add_neighbour_to_cell(c1, c2, NSD_2);
                    c2->neighbour_list[NSD_1] =
                        add_neighbour_to_cell(c2, c1, NSD_1);
                    /*c2->neighbour_list[NSD_2] =
                       add_neighbour_to_cell(c2, c1, NSD_2); */

                    if (VERBOSE) {
                        fprintf(stderr, "make_layer : c1=%p c2=%p\n", c1,
                                c2);
                        fprintf(stderr,
                                "make_layer : c1->nsd2 = %p, c2->nsd1 = %p\n",
                                get_cell_from_list(c1->neighbour_list
                                                   [NSD_2], 0),
                                get_cell_from_list(c2->neighbour_list
                                                   [NSD_1], 0));
                    }

                } else {
                    if (VERBOSE) {
                        fprintf(stderr,
                                "make_layer : c1 is in [180,360\n");
                    }
                    c1->neighbour_list[NSD_1] =
                        add_neighbour_to_cell(c1, c2, NSD_1);
                    c2->neighbour_list[NSD_2] =
                        add_neighbour_to_cell(c2, c1, NSD_2);
                    /*c2->neighbour_list[NSD_1] =
                       add_neighbour_to_cell(c2, c1, NSD_1); */
                }
            }

            c1 = get_cell_from_list(c1->neighbour_list[EAST_D], 0);
            c1_lon += plon;
            nl++;
        }
        while (c1 && nl < nb_meridian / 2);
    }

    /*----------------*/
    /* and North Pole */

    /*----------------*/
    if ((int) (mp->lat_max) == 90) {
        if (DEBUG)
            fprintf(stderr, "make_layer : link north (topo)\n");

        c1 = first_m;
        if (!cell2return) {
            while (c1->neighbour_list[NSD_1]) {
                c1 = get_cell_from_list(c1->neighbour_list[NSD_1], 0);
            }
        }

        /* dump couronne */
        /*if (DEBUG) {
           n = 0;
           fprintf(stderr, "\ncouronne = ");
           c2 = c1;
           while (n < nb_meridian) {
           n++;
           fprintf(stderr, "%p(%d), ", c2, n);
           c2 = get_cell_from_list(c2->neighbour_list[EAST_D], 0);
           }
           fprintf(stderr, "\n");
           } */

        first_cell = c1;
        c1_lon = mp->lon_min;
        plon = mp->lon_unit_size * layer->lon_unit;

        nl = 0;                 /* number of move to complete the pole link */
        do {
            if (c1_lon + 180. < mp->lon_max - plon + EPS) {
                /* link is possible */
                /*if (DEBUG)
                   fprintf(stderr,
                   "link possible for cell c1 = %p (lon=%.1f)",
                   c1, c1_lon);
                 */

                /* we go on the cell to link with c1 */
                n = 0;
                c2 = c1;
                if (VERBOSE)
                    fprintf(stderr,
                            "make_layer : going to cell c2 to link with c1 : ");
                while (n < nb_max_meridian / 2) {
                    if (VERBOSE)
                        fprintf(stderr, "+");
                    c2 = get_cell_from_list(c2->neighbour_list[EAST_D], 0);
                    n++;
                }
                if (VERBOSE)
                    fprintf(stderr, "\n");

                /*if (DEBUG)
                   fprintf(stderr, "with c2 = %p\n", c2);
                 */

                /* the link */
                if (is_in_interval
                    (modulo360(c1_lon, 0), 0. - EPS, 180. - EPS)
                    && !is_in_interval(180., modulo360(c1_lon, 0) - EPS,
                                       modulo360(c1_lon + plon,
                                                 1) - EPS)) {
                    if (VERBOSE)
                        fprintf(stderr, "make_layer : c1 is in [0,180[\n");
                    c1->neighbour_list[NSD_1] =
                        add_neighbour_to_cell(c1, c2, NSD_1);
                    c2->neighbour_list[NSD_2] =
                        add_neighbour_to_cell(c2, c1, NSD_2);
                    /*c2->neighbour_list[NSD_1] =
                       add_neighbour_to_cell(c2, c1, NSD_1); */
                } else {
                    if (VERBOSE)
                        fprintf(stderr,
                                "make_layer : c1 is in [180,360\n");
                    c1->neighbour_list[NSD_2] =
                        add_neighbour_to_cell(c1, c2, NSD_2);
                    c2->neighbour_list[NSD_1] =
                        add_neighbour_to_cell(c2, c1, NSD_1);
                    /*c2->neighbour_list[NSD_2] =
                       add_neighbour_to_cell(c2, c1, NSD_2); */
                }
            }
            c1 = get_cell_from_list(c1->neighbour_list[EAST_D], 0);
            c1_lon += plon;
            nl++;
        }
        while (c1 && nl < nb_meridian / 2);
    }
}
コード例 #6
0
/* This function is called when a node receives a message.
 *
 * \param message the message to handle (don't touch it afterward: it will be destroyed, reused or forwarded)
 */
void Node::handleMessage(ChordMessage* message)
{
  switch (message->type) {
  case FIND_SUCCESSOR:
    XBT_DEBUG("Received a 'Find Successor' request from %s for id %d", message->issuer_host_name.c_str(),
        message->request_id);
    // is my successor the successor?
    if (is_in_interval(message->request_id, id_ + 1, fingers_[0])) {
      message->type = FIND_SUCCESSOR_ANSWER;
      message->answer_id = fingers_[0];
      XBT_DEBUG("Sending back a 'Find Successor Answer' to %s (mailbox %s): the successor of %d is %d",
                message->issuer_host_name.c_str(), message->answer_to->get_cname(), message->request_id,
                message->answer_id);
      message->answer_to->put_init(message, 10)->detach(ChordMessage::destroy);
    } else {
      // otherwise, forward the request to the closest preceding finger in my table
      int closest = closestPrecedingFinger(message->request_id);
      XBT_DEBUG("Forwarding the 'Find Successor' request for id %d to my closest preceding finger %d",
          message->request_id, closest);
      simgrid::s4u::MailboxPtr mailbox = simgrid::s4u::Mailbox::by_name(std::to_string(closest));
      mailbox->put_init(message, 10)->detach(ChordMessage::destroy);
    }
    break;

  case GET_PREDECESSOR:
    XBT_DEBUG("Receiving a 'Get Predecessor' request from %s", message->issuer_host_name.c_str());
    message->type = GET_PREDECESSOR_ANSWER;
    message->answer_id = pred_id_;
    XBT_DEBUG("Sending back a 'Get Predecessor Answer' to %s via mailbox '%s': my predecessor is %d",
              message->issuer_host_name.c_str(), message->answer_to->get_cname(), message->answer_id);
    message->answer_to->put_init(message, 10)->detach(ChordMessage::destroy);
    break;

  case NOTIFY:
    // someone is telling me that he may be my new predecessor
    XBT_DEBUG("Receiving a 'Notify' request from %s", message->issuer_host_name.c_str());
    notify(message->request_id);
    delete message;
    break;

  case PREDECESSOR_LEAVING:
    // my predecessor is about to quit
    XBT_DEBUG("Receiving a 'Predecessor Leaving' message from %s", message->issuer_host_name.c_str());
    // modify my predecessor
    setPredecessor(message->request_id);
    delete message;
    /*TODO :
      >> notify my new predecessor
      >> send a notify_predecessors !!
     */
    break;

  case SUCCESSOR_LEAVING:
    // my successor is about to quit
    XBT_DEBUG("Receiving a 'Successor Leaving' message from %s", message->issuer_host_name.c_str());
    // modify my successor FIXME : this should be implicit ?
    setFinger(0, message->request_id);
    delete message;
    /* TODO
       >> notify my new successor
       >> update my table & predecessors table */
    break;

  case PREDECESSOR_ALIVE:
    XBT_DEBUG("Receiving a 'Predecessor Alive' request from %s", message->issuer_host_name.c_str());
    message->type = PREDECESSOR_ALIVE_ANSWER;
    XBT_DEBUG("Sending back a 'Predecessor Alive Answer' to %s (mailbox %s)", message->issuer_host_name.c_str(),
              message->answer_to->get_cname());
    message->answer_to->put_init(message, 10)->detach(ChordMessage::destroy);
    break;

  default:
    XBT_DEBUG("Ignoring unexpected message: %d from %s", message->type, message->issuer_host_name.c_str());
    delete message;
  }
}