<commit_before>/*
 * Open-MX
 * Copyright © INRIA 2007-2008 (see AUTHORS file)
 *
 * The development of this software has been funded by Myricom, Inc.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation; either version 2.1 of the License, or (at
 * your option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 *
 * See the GNU Lesser General Public License in COPYING.LGPL for more details.
 */

#include <stdlib.h>
#include <sys/ioctl.h>

#include "omx_lib.h"
#include "omx_request.h"
#include "omx_wire_access.h"
#include "omx_lib_wire.h"
#include "omx_segments.h"

/*
 * Partner session ids management:
 *
 * Each endpoint gets a random session identity number from the driver.
 * The endpoint key/filter is only used to filter connect requests in
 * the library. All other messages will be filtered by the driver/mcp
 * through this session number, which won't be the same across multiple
 * runs. All remote peers pass their session id to us during the connect
 * handshake.
 *
 * Each partner structure actually stores two session numbers.
 * + true_session_id is the regular one that we get back in the connect
 *   reply and may be used for normal sends.
 * + back_session_id is obtained from the connect request of the remote
 *   peer and we will use for special "back" communications such as acks
 *   and notify after large messages.
 *
 * Both true_ and back_session_id are set when we receive a connect
 * reply. Only back_session_id is set on connect request.
 * So back_session_id may be set without true_session_id, while
 * true_session_id being set implies that back_session_id is set to
 * the same.
 *
 * Updating rules for true_ and back_session_id:
 * + If true_session_id changes on reply/request, this is the first
 *   connect (true_session_id was unset), or the remote peer has
 *   changed (true_session_id was already set), we reset our send
 *   seqnums to what the remote peer wants to receive.
 * + If back_session_id changes on reply, this is the first reply
 *   (back_session_id was unset), or the remote peer has changed
 *   (back_session_id was already set), we reset our receive seqnums.
 * + If back_session_id changes on reply/request (and it was already
 *   set), the remote peer has changed, we cleanup our stuff. It also
 *   implies that true_session_id was unset or would change.
 */

/******************************
 * Endpoint address management
 */

/* API omx_get_endpoint_addr */
omx_return_t
omx_get_endpoint_addr(omx_endpoint_t endpoint,
		      omx_endpoint_addr_t *endpoint_addr)
{
  /* no need to lock here, there's no possible race condition or so */

  omx__partner_session_to_addr(endpoint->myself, endpoint->desc->session_id, endpoint_addr);
  return OMX_SUCCESS;
}

/* API omx_decompose_endpoint_addr */
omx_return_t
omx_decompose_endpoint_addr(omx_endpoint_addr_t endpoint_addr,
			    uint64_t *nic_id, uint32_t *endpoint_id)
{
  struct omx__partner *partner = omx__partner_from_addr(&endpoint_addr);

  /* no need to lock here, there's no possible race condition or so */

  *nic_id = partner->board_addr;
  *endpoint_id = partner->endpoint_index;
  return OMX_SUCCESS;
}

/* API omx_decompose_endpoint_addr_with_session */
omx_return_t
omx_decompose_endpoint_addr_with_session(omx_endpoint_addr_t endpoint_addr,
					 uint64_t *nic_id, uint32_t *endpoint_id, uint32_t *session_id)
{
  struct omx__partner *partner = omx__partner_from_addr(&endpoint_addr);

  /* no need to lock here, there's no possible race condition or so */

  *nic_id = partner->board_addr;
  *endpoint_id = partner->endpoint_index;
  *session_id = ((struct omx__endpoint_addr *) &endpoint_addr)->session_id;
  return OMX_SUCCESS;
}

/*********************
 * Partner management
 */

void
omx__partner_reset(struct omx__partner *partner)
{
  INIT_LIST_HEAD(&partner->non_acked_req_q);
  INIT_LIST_HEAD(&partner->pending_connect_req_q);
  INIT_LIST_HEAD(&partner->partial_recv_req_q);
  INIT_LIST_HEAD(&partner->early_recv_q);
  INIT_LIST_HEAD(&partner->throttling_send_req_q);

  partner->true_session_id = -1; /* will be initialized when we will be connected to the peer */
  partner->back_session_id = -1; /* will be initialized when the partner will connect to me */
  partner->next_send_seq = -1; /* will be initialized when the partner will reply to my connect */
  partner->next_acked_send_seq = -1; /* will be initialized when the partner will reply to my connect */
  OMX__SEQNUM_RESET(partner->next_match_recv_seq); /* will force the sender's send seq through the connect */
  partner->next_frag_recv_seq = partner->next_match_recv_seq; /* will force the sender's send seq through the connect */
  partner->last_acked_recv_seq = partner->next_frag_recv_seq; /* nothing to ack yet */
  partner->connect_seqnum = 0;
  partner->last_send_acknum = 0;
  partner->last_recv_acknum = 0;
  partner->throttling_sends_nr = 0;

  if (partner->need_ack != OMX__PARTNER_NEED_NO_ACK) {
    partner->need_ack = OMX__PARTNER_NEED_NO_ACK;
    list_del(&partner->endpoint_partners_to_ack_elt);
  }
}

omx_return_t
omx__partner_create(struct omx_endpoint *ep, uint16_t peer_index,
		    uint64_t board_addr, uint8_t endpoint_index,
		    struct omx__partner ** partnerp)
{
  struct omx__partner * partner;
  uint32_t partner_index;

  partner = malloc(sizeof(*partner));
  if (unlikely(!partner))
    return OMX_NO_RESOURCES;

  partner->board_addr = board_addr;
  partner->endpoint_index = endpoint_index;
  partner->peer_index = peer_index;
  partner->localization = OMX__PARTNER_LOCALIZATION_UNKNOWN; /* will be set by omx__partner_check_localization() */
  partner->need_ack = OMX__PARTNER_NEED_NO_ACK;

  omx__partner_reset(partner);

  partner_index = ((uint32_t) endpoint_index)
    + ((uint32_t) peer_index) * omx__driver_desc->endpoint_max;
  ep->partners[partner_index] = partner;

  *partnerp = partner;
  omx__debug_printf(CONNECT, "created peer %d %d\n", peer_index, endpoint_index);

  return OMX_SUCCESS;
}

static INLINE void<commit_msg>make sure partner's next_match_recv_seq is correctly initialized<commit_after>/*
 * Open-MX
 * Copyright © INRIA 2007-2008 (see AUTHORS file)
 *
 * The development of this software has been funded by Myricom, Inc.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation; either version 2.1 of the License, or (at
 * your option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 *
 * See the GNU Lesser General Public License in COPYING.LGPL for more details.
 */

#include <stdlib.h>
#include <sys/ioctl.h>

#include "omx_lib.h"
#include "omx_request.h"
#include "omx_wire_access.h"
#include "omx_lib_wire.h"
#include "omx_segments.h"

/*
 * Partner session ids management:
 *
 * Each endpoint gets a random session identity number from the driver.
 * The endpoint key/filter is only used to filter connect requests in
 * the library. All other messages will be filtered by the driver/mcp
 * through this session number, which won't be the same across multiple
 * runs. All remote peers pass their session id to us during the connect
 * handshake.
 *
 * Each partner structure actually stores two session numbers.
 * + true_session_id is the regular one that we get back in the connect
 *   reply and may be used for normal sends.
 * + back_session_id is obtained from the connect request of the remote
 *   peer and we will use for special "back" communications such as acks
 *   and notify after large messages.
 *
 * Both true_ and back_session_id are set when we receive a connect
 * reply. Only back_session_id is set on connect request.
 * So back_session_id may be set without true_session_id, while
 * true_session_id being set implies that back_session_id is set to
 * the same.
 *
 * Updating rules for true_ and back_session_id:
 * + If true_session_id changes on reply/request, this is the first
 *   connect (true_session_id was unset), or the remote peer has
 *   changed (true_session_id was already set), we reset our send
 *   seqnums to what the remote peer wants to receive.
 * + If back_session_id changes on reply, this is the first reply
 *   (back_session_id was unset), or the remote peer has changed
 *   (back_session_id was already set), we reset our receive seqnums.
 * + If back_session_id changes on reply/request (and it was already
 *   set), the remote peer has changed, we cleanup our stuff. It also
 *   implies that true_session_id was unset or would change.
 */

/******************************
 * Endpoint address management
 */

/* API omx_get_endpoint_addr */
omx_return_t
omx_get_endpoint_addr(omx_endpoint_t endpoint,
		      omx_endpoint_addr_t *endpoint_addr)
{
  /* no need to lock here, there's no possible race condition or so */

  omx__partner_session_to_addr(endpoint->myself, endpoint->desc->session_id, endpoint_addr);
  return OMX_SUCCESS;
}

/* API omx_decompose_endpoint_addr */
omx_return_t
omx_decompose_endpoint_addr(omx_endpoint_addr_t endpoint_addr,
			    uint64_t *nic_id, uint32_t *endpoint_id)
{
  struct omx__partner *partner = omx__partner_from_addr(&endpoint_addr);

  /* no need to lock here, there's no possible race condition or so */

  *nic_id = partner->board_addr;
  *endpoint_id = partner->endpoint_index;
  return OMX_SUCCESS;
}

/* API omx_decompose_endpoint_addr_with_session */
omx_return_t
omx_decompose_endpoint_addr_with_session(omx_endpoint_addr_t endpoint_addr,
					 uint64_t *nic_id, uint32_t *endpoint_id, uint32_t *session_id)
{
  struct omx__partner *partner = omx__partner_from_addr(&endpoint_addr);

  /* no need to lock here, there's no possible race condition or so */

  *nic_id = partner->board_addr;
  *endpoint_id = partner->endpoint_index;
  *session_id = ((struct omx__endpoint_addr *) &endpoint_addr)->session_id;
  return OMX_SUCCESS;
}

/*********************
 * Partner management
 */

void
omx__partner_reset(struct omx__partner *partner)
{
  INIT_LIST_HEAD(&partner->non_acked_req_q);
  INIT_LIST_HEAD(&partner->pending_connect_req_q);
  INIT_LIST_HEAD(&partner->partial_recv_req_q);
  INIT_LIST_HEAD(&partner->early_recv_q);
  INIT_LIST_HEAD(&partner->throttling_send_req_q);

  partner->true_session_id = -1; /* will be initialized when we will be connected to the peer */
  partner->back_session_id = -1; /* will be initialized when the partner will connect to me */
  partner->next_send_seq = -1; /* will be initialized when the partner will reply to my connect */
  partner->next_acked_send_seq = -1; /* will be initialized when the partner will reply to my connect */
  OMX__SEQNUM_RESET(partner->next_match_recv_seq); /* will force the sender's send seq through the connect */
  partner->next_frag_recv_seq = partner->next_match_recv_seq; /* will force the sender's send seq through the connect */
  partner->last_acked_recv_seq = partner->next_frag_recv_seq; /* nothing to ack yet */
  partner->connect_seqnum = 0;
  partner->last_send_acknum = 0;
  partner->last_recv_acknum = 0;
  partner->throttling_sends_nr = 0;

  if (partner->need_ack != OMX__PARTNER_NEED_NO_ACK) {
    partner->need_ack = OMX__PARTNER_NEED_NO_ACK;
    list_del(&partner->endpoint_partners_to_ack_elt);
  }
}

omx_return_t
omx__partner_create(struct omx_endpoint *ep, uint16_t peer_index,
		    uint64_t board_addr, uint8_t endpoint_index,
		    struct omx__partner ** partnerp)
{
  struct omx__partner * partner;
  uint32_t partner_index;

  partner = malloc(sizeof(*partner));
  if (unlikely(!partner))
    return OMX_NO_RESOURCES;

  partner->board_addr = board_addr;
  partner->endpoint_index = endpoint_index;
  partner->peer_index = peer_index;
  partner->localization = OMX__PARTNER_LOCALIZATION_UNKNOWN; /* will be set by omx__partner_check_localization() */
  partner->next_match_recv_seq = 0; /* first session, seqnum will be initialized by omx__partner_reset() */
  partner->need_ack = OMX__PARTNER_NEED_NO_ACK;

  omx__partner_reset(partner);

  partner_index = ((uint32_t) endpoint_index)
    + ((uint32_t) peer_index) * omx__driver_desc->endpoint_max;
  ep->partners[partner_index] = partner;

  *partnerp = partner;
  omx__debug_printf(CONNECT, "created peer %d %d\n", peer_index, endpoint_index);

  return OMX_SUCCESS;
}

static INLINE void
{'fraction_non_alphanumeric': 0.08792764451435313, 'fraction_numerical': 0.006213134093590248, 'mean_word_length': 4.62406015037594, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 80, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3592197', 'n_tokens_mistral': 4115, 'n_tokens_neox': 4029, 'n_words': 1277}