/* --------------------------------------------------------------------------*/
int player_send_message(int pid, player_cmd_t *cmd)
{
    player_cmd_t *mycmd;
    int r = -1;
    play_para_t *player_para;
    char buf[512];

    player_para = player_open_pid_data(pid);
    if (player_para == NULL) {
        return PLAYER_NOT_VALID_PID;
    }

    if (player_get_state(pid) == PLAYER_EXIT) {
        player_close_pid_data(pid);
        return PLAYER_SUCCESS;
    }

    mycmd = message_alloc();
    if (mycmd) {
        memcpy(mycmd, cmd, sizeof(*cmd));
        r = send_message_by_pid(pid, mycmd);
        if (cmd2str(cmd, buf) != -1) {
            log_print("[%s]cmd = %s\n", __FUNCTION__, buf);
        }
    } else {
        r = PLAYER_NOMEM;
    }
    player_close_pid_data(pid);
    return r;
}
/* --------------------------------------------------------------------------*/
int player_stop_async(int pid)
{
    player_cmd_t *cmd;
    int r = PLAYER_SUCCESS;
    play_para_t *player_para;
    player_status sta;

    player_para = player_open_pid_data(pid);

    if (player_para == NULL) {
        return PLAYER_NOT_VALID_PID;
    }

    sta = get_player_state(player_para);
    log_print("[player_stop]player_status=%x\n", sta);
    if (PLAYER_THREAD_IS_STOPPED(sta)) {
        player_close_pid_data(pid);
        log_print("[player_stop]pid=%d thread is already stopped\n", pid);
        return PLAYER_SUCCESS;
    }
    cmd = message_alloc();
    if (cmd) {
        cmd->ctrl_cmd = CMD_STOP;
        ffmpeg_interrupt(player_para->thread_mgt.pthread_id);
        r = send_message(player_para, cmd);
    } else {
        r = PLAYER_NOMEM;
    }

    player_close_pid_data(pid);

    return r;
}
Exemple #3
0
po_message_t
po_message_create (void)
{
  lex_pos_ty pos = { NULL, 0 };

  return (po_message_t) message_alloc (NULL, NULL, NULL, NULL, 0, &pos);
}
/* --------------------------------------------------------------------------*/
int player_start_play(int pid)
{
    player_cmd_t *cmd;
    int r = PLAYER_SUCCESS;
    play_para_t *player_para;

    log_print("[player_start_play:enter]pid=%d\n", pid);

    player_para = player_open_pid_data(pid);
    if (player_para == NULL) {
        return PLAYER_NOT_VALID_PID;
    }

    cmd = message_alloc();
    if (cmd) {
        cmd->ctrl_cmd = CMD_START;
        r = send_message(player_para, cmd);
    } else {
        r = PLAYER_NOMEM;
    }

    player_close_pid_data(pid);
    log_print("[player_start_play:exit]pid = %d\n", pid);

    return r;
}
struct cfw_message * cfw_clone_message(struct cfw_message * msg) {
    struct cfw_message * ret = (struct cfw_message *)
            message_alloc(CFW_MESSAGE_LEN(msg), NULL);
    if (ret == NULL) {
        pr_error(LOG_MODULE_CFW, "%s: Error allocating message", __func__);
    } else {
		memcpy(ret, msg, CFW_MESSAGE_LEN(msg));
    }
    return ret;
}
static void circular_storage_shutdown(service_t *svc, struct cfw_message *msg)
{
	struct cfw_message *sm = (struct cfw_message *)message_alloc(
		sizeof(*sm), NULL);

	/* In order to ensure that any pending requests are processed prior to the
	 * service shutdown, send a message to self so it will be processed after
	 * all other pending requests.
	 */
	CFW_MESSAGE_ID(sm) = MSG_ID_LL_CIRCULAR_STORAGE_SHUTDOWN_REQ;
	CFW_MESSAGE_DST(sm) = circular_storage_service.port_id;
	CFW_MESSAGE_SRC(sm) = circular_storage_service.port_id;
	CFW_MESSAGE_PRIV(sm) = msg;
	cfw_send_message(sm);
}
/* --------------------------------------------------------------------------*/
int player_stop(int pid)
{
    player_cmd_t *cmd;
    int r = PLAYER_SUCCESS;
    play_para_t *player_para;
    player_status sta;

    log_print("[player_stop:enter]pid=%d\n", pid);

    player_para = player_open_pid_data(pid);
    if (player_para == NULL) {
        return PLAYER_NOT_VALID_PID;
    }

    sta = get_player_state(player_para);
    log_print("[player_stop]player_status=%x\n", sta);
    if (PLAYER_THREAD_IS_STOPPED(sta)) {
        player_close_pid_data(pid);
        log_print("[player_stop]pid=%d thread is already stopped\n", pid);
        return PLAYER_SUCCESS;
    }
    /*if (player_para->pFormatCtx) {
        av_ioctrl(player_para->pFormatCtx, AVIOCTL_STOP, 0, 0);
    }*/

    cmd = message_alloc();
    if (cmd) {
        cmd->ctrl_cmd = CMD_STOP;
        ffmpeg_interrupt(player_para->thread_mgt.pthread_id);
        r = send_message(player_para, cmd);
        r = player_thread_wait_exit(player_para);
        log_print("[player_stop:%d]wait player_theadpid[%d] r = %d\n", __LINE__, player_para->player_id, r);
        clear_all_message(player_para);
        ffmpeg_uninterrupt(player_para->thread_mgt.pthread_id);
    } else {
        r = PLAYER_NOMEM;
    }

    player_close_pid_data(pid);
    log_print("[player_stop:exit]pid=%d\n", pid);

    return r;
}
Exemple #8
0
message_ty *
message_copy (message_ty *mp)
{
  message_ty *result;
  size_t j, i;

  result = message_alloc (mp->msgctxt != NULL ? xstrdup (mp->msgctxt) : NULL,
                          xstrdup (mp->msgid), mp->msgid_plural,
                          mp->msgstr, mp->msgstr_len, &mp->pos);

  if (mp->comment)
    {
      for (j = 0; j < mp->comment->nitems; ++j)
        message_comment_append (result, mp->comment->item[j]);
    }
  if (mp->comment_dot)
    {
      for (j = 0; j < mp->comment_dot->nitems; ++j)
        message_comment_dot_append (result, mp->comment_dot->item[j]);
    }
  result->is_fuzzy = mp->is_fuzzy;
  for (i = 0; i < NFORMATS; i++)
    result->is_format[i] = mp->is_format[i];
  result->range = mp->range;
  result->do_wrap = mp->do_wrap;
  for (i = 0; i < NSYNTAXCHECKS; i++)
    result->do_syntax_check[i] = mp->do_syntax_check[i];
  for (j = 0; j < mp->filepos_count; ++j)
    {
      lex_pos_ty *pp = &mp->filepos[j];
      message_comment_filepos (result, pp->file_name, pp->line_number);
    }
  result->prev_msgctxt =
    (mp->prev_msgctxt != NULL ? xstrdup (mp->prev_msgctxt) : NULL);
  result->prev_msgid =
    (mp->prev_msgid != NULL ? xstrdup (mp->prev_msgid) : NULL);
  result->prev_msgid_plural =
    (mp->prev_msgid_plural != NULL ? xstrdup (mp->prev_msgid_plural) : NULL);
  return result;
}
Exemple #9
0
/* Delivers a notification which matches the receiver's subscription
 * expression */
static void
notify_cb(elvin_handle_t handle,
          elvin_subscription_t subscription,
          elvin_notification_t notification,
          int is_secure,
          void *rock,
          elvin_error_t error)
{
    usenet_sub_t self = (usenet_sub_t)rock;
    message_t message;
    elvin_basetypes_t type;
    elvin_value_t value;
    char *string;
    char *newsgroups;
    char *name;
    char *subject;
    char *mime_type;
    char *mime_args;
    char *attachment = NULL;
    size_t length;
    char *buffer = NULL;

    /* If we don't have a callback than bail out now */
    if (self->callback == NULL) {
        return;
    }

    /* Get the newsgroups to which the message was posted */
    if (elvin_notification_get(notification, NEWSGROUPS, &type, &value,
                               error) &&
        type == ELVIN_STRING) {
        string = value.s;
    } else {
        string = "news";
    }

    /* Prepend `usenet:' to the beginning of the group field */
    length = strlen(USENET_PREFIX) + strlen(string) - 1;
    newsgroups = malloc(length);
    if (newsgroups == NULL) {
        return;
    }

    snprintf(newsgroups, length, USENET_PREFIX, string);

    /* Get the name from the FROM_NAME field (if provided) */
    if (elvin_notification_get(notification, FROM_NAME, &type, &value,
                               error) &&
        type == ELVIN_STRING) {
        name = value.s;
    } else {
        /* If no FROM_NAME field then try FROM_EMAIL */
        if (elvin_notification_get(notification, FROM_EMAIL, &type, &value,
                                   error) &&
            type == ELVIN_STRING) {
            name = value.s;
        } else {
            /* If no FROM_EMAIL then try FROM */
            if (elvin_notification_get(notification, FROM, &type, &value,
                                       error) &&
                type == ELVIN_STRING) {
                name = value.s;
            } else {
                name = "anonymous";
            }
        }
    }

    /* Get the SUBJECT field (if provided) */
    if (elvin_notification_get(notification, SUBJECT, &type, &value,
                               error) &&
        type == ELVIN_STRING) {
        subject = value.s;
    } else {
        subject = "[no subject]";
    }

    /* Get the MIME_ARGS field (if provided) */
    if (elvin_notification_get(notification, MIME_ARGS, &type, &value,
                               error) &&
        type == ELVIN_STRING) {
        mime_args = value.s;

        /* Get the MIME_TYPE field (if provided) */
        if (elvin_notification_get(notification, MIME_TYPE, &type, &value,
                                   error) &&
            type == ELVIN_STRING) {
            mime_type = value.s;
        } else {
            mime_type = URL_MIME_TYPE;
        }
    } else {
        /* No MIME_ARGS provided.  Construct one using the Message-ID
         * field */
        if (elvin_notification_get(notification, MESSAGE_ID, &type, &value,
                                   error) &&
            type == ELVIN_STRING) {
            char *message_id = value.s;
            char *news_host;

            if (elvin_notification_get(notification, X_NNTP_HOST, &type,
                                       &value, error) &&
                type == ELVIN_STRING) {
                news_host = value.s;
            } else {
                news_host = "news";
            }

            length = strlen(NEWS_URL) + strlen(news_host) +
                     strlen(message_id) - 3;
            buffer = malloc(length);
            if (buffer == NULL) {
                mime_type = NULL;
                mime_args = NULL;
            } else {
                snprintf(buffer, length, NEWS_URL, news_host, message_id);
                mime_args = buffer;
                mime_type = NEWS_MIME_TYPE;
            }
        } else {
            mime_type = NULL;
            mime_args = NULL;
        }
    }

    /* Convert the mime type and args into an attachment */
    if (mime_type == NULL || mime_args == NULL) {
        attachment = NULL;
        length = 0;
    } else {
        length = strlen(ATTACHMENT_FMT) + strlen(mime_type) + strlen(
            mime_args) - 4;
        attachment = malloc(length + 1);
        if (attachment == NULL) {
            length = 0;
        } else {
            snprintf(attachment, length + 1, ATTACHMENT_FMT,
                     mime_type, mime_args);
        }
    }

    /* Construct a message out of all of that */
    message = message_alloc(NULL, newsgroups, name, subject, 300,
                            attachment, length - 1,
                            NULL, NULL, NULL, NULL);
    if (message != NULL) {
        /* Deliver the message */
        self->callback(self->rock, message, False);
    }

    /* Clean up */
    free(newsgroups);
    if (buffer != NULL) {
        free(buffer);
    }

    if (attachment != NULL) {
        free(attachment);
    }
}
Exemple #10
0
/* Reads an existing .mo file and adds the messages to mlp.  */
void
read_mo_file (message_list_ty *mlp, const char *filename)
{
  FILE *fp;
  struct binary_mo_file bf;
  struct mo_file_header header;
  unsigned int i;
  static lex_pos_ty pos = { __FILE__, __LINE__ };

  if (strcmp (filename, "-") == 0 || strcmp (filename, "/dev/stdin") == 0)
    {
      fp = stdin;
      SET_BINARY (fileno (fp));
    }
  else
    {
      fp = fopen (filename, "rb");
      if (fp == NULL)
	error (EXIT_FAILURE, errno,
	       _("error while opening \"%s\" for reading"), filename);
    }

  /* Read the file contents into memory.  */
  read_binary_mo_file (&bf, fp, filename);

  /* Get a 32-bit number from the file header.  */
# define GET_HEADER_FIELD(field) \
    get_uint32 (&bf, offsetof (struct mo_file_header, field))

  /* We must grope the file to determine which endian it is.
     Perversity of the universe tends towards maximum, so it will
     probably not match the currently executing architecture.  */
  bf.endian = MO_BIG_ENDIAN;
  header.magic = GET_HEADER_FIELD (magic);
  if (header.magic != _MAGIC)
    {
      bf.endian = MO_LITTLE_ENDIAN;
      header.magic = GET_HEADER_FIELD (magic);
      if (header.magic != _MAGIC)
	{
	unrecognised:
	  error (EXIT_FAILURE, 0, _("file \"%s\" is not in GNU .mo format"),
		 filename);
	}
    }

  header.revision = GET_HEADER_FIELD (revision);

  /* We support only the major revisions 0 and 1.  */
  switch (header.revision >> 16)
    {
    case 0:
    case 1:
      /* Fill the header parts that apply to major revisions 0 and 1.  */
      header.nstrings = GET_HEADER_FIELD (nstrings);
      header.orig_tab_offset = GET_HEADER_FIELD (orig_tab_offset);
      header.trans_tab_offset = GET_HEADER_FIELD (trans_tab_offset);
      header.hash_tab_size = GET_HEADER_FIELD (hash_tab_size);
      header.hash_tab_offset = GET_HEADER_FIELD (hash_tab_offset);

      for (i = 0; i < header.nstrings; i++)
	{
	  message_ty *mp;
	  char *msgid;
	  size_t msgid_len;
	  char *msgstr;
	  size_t msgstr_len;

	  /* Read the msgid.  */
	  msgid = get_string (&bf, header.orig_tab_offset + i * 8,
			      &msgid_len);

	  /* Read the msgstr.  */
	  msgstr = get_string (&bf, header.trans_tab_offset + i * 8,
			       &msgstr_len);

	  mp = message_alloc (msgid,
			      (strlen (msgid) + 1 < msgid_len
			       ? msgid + strlen (msgid) + 1
			       : NULL),
			      msgstr, msgstr_len,
			      &pos);
	  message_list_append (mlp, mp);
	}

      switch (header.revision & 0xffff)
	{
	case 0:
	  break;
	case 1:
	default:
	  /* Fill the header parts that apply to minor revision >= 1.  */
	  header.n_sysdep_segments = GET_HEADER_FIELD (n_sysdep_segments);
	  header.sysdep_segments_offset =
	    GET_HEADER_FIELD (sysdep_segments_offset);
	  header.n_sysdep_strings = GET_HEADER_FIELD (n_sysdep_strings);
	  header.orig_sysdep_tab_offset =
	    GET_HEADER_FIELD (orig_sysdep_tab_offset);
	  header.trans_sysdep_tab_offset =
	    GET_HEADER_FIELD (trans_sysdep_tab_offset);

	  for (i = 0; i < header.n_sysdep_strings; i++)
	    {
	      message_ty *mp;
	      char *msgid;
	      size_t msgid_len;
	      char *msgstr;
	      size_t msgstr_len;
	      nls_uint32 offset;

	      /* Read the msgid.  */
	      offset = get_uint32 (&bf, header.orig_sysdep_tab_offset + i * 4);
	      msgid = get_sysdep_string (&bf, offset, &header, &msgid_len);

	      /* Read the msgstr.  */
	      offset = get_uint32 (&bf, header.trans_sysdep_tab_offset + i * 4);
	      msgstr = get_sysdep_string (&bf, offset, &header, &msgstr_len);

	      mp = message_alloc (msgid,
				  (strlen (msgid) + 1 < msgid_len
				   ? msgid + strlen (msgid) + 1
				   : NULL),
				  msgstr, msgstr_len,
				  &pos);
	      message_list_append (mlp, mp);
	    }
	  break;
	}
      break;

    default:
      goto unrecognised;
    }

  if (fp != stdin)
    fclose (fp);
}
/* Reads an existing .mo file and adds the messages to mlp.  */
void
read_mo_file (message_list_ty *mlp, const char *filename)
{
  FILE *fp;
  struct binary_mo_file bf;
  struct mo_file_header header;
  unsigned int i;
  static lex_pos_ty pos = { __FILE__, __LINE__ };

  if (strcmp (filename, "-") == 0 || strcmp (filename, "/dev/stdin") == 0)
    {
      fp = stdin;
      SET_BINARY (fileno (fp));
    }
  else
    {
      fp = fopen (filename, "rb");
      if (fp == NULL)
        error (EXIT_FAILURE, errno,
               _("error while opening \"%s\" for reading"), filename);
    }

  /* Read the file contents into memory.  */
  read_binary_mo_file (&bf, fp, filename);

  /* Get a 32-bit number from the file header.  */
# define GET_HEADER_FIELD(field) \
    get_uint32 (&bf, offsetof (struct mo_file_header, field))

  /* We must grope the file to determine which endian it is.
     Perversity of the universe tends towards maximum, so it will
     probably not match the currently executing architecture.  */
  bf.endian = MO_BIG_ENDIAN;
  header.magic = GET_HEADER_FIELD (magic);
  if (header.magic != _MAGIC)
    {
      bf.endian = MO_LITTLE_ENDIAN;
      header.magic = GET_HEADER_FIELD (magic);
      if (header.magic != _MAGIC)
        {
        unrecognised:
          error (EXIT_FAILURE, 0, _("file \"%s\" is not in GNU .mo format"),
                 filename);
        }
    }

  header.revision = GET_HEADER_FIELD (revision);

  /* We support only the major revisions 0 and 1.  */
  switch (header.revision >> 16)
    {
    case 0:
    case 1:
      /* Fill the header parts that apply to major revisions 0 and 1.  */
      header.nstrings = GET_HEADER_FIELD (nstrings);
      header.orig_tab_offset = GET_HEADER_FIELD (orig_tab_offset);
      header.trans_tab_offset = GET_HEADER_FIELD (trans_tab_offset);
      header.hash_tab_size = GET_HEADER_FIELD (hash_tab_size);
      header.hash_tab_offset = GET_HEADER_FIELD (hash_tab_offset);

      for (i = 0; i < header.nstrings; i++)
        {
          message_ty *mp;
          char *msgctxt;
          char *msgid;
          size_t msgid_len;
          char *separator;
          char *msgstr;
          size_t msgstr_len;

          /* Read the msgctxt and msgid.  */
          msgid = get_string (&bf, header.orig_tab_offset + i * 8,
                              &msgid_len);
          /* Split into msgctxt and msgid.  */
          separator = strchr (msgid, MSGCTXT_SEPARATOR);
          if (separator != NULL)
            {
              /* The part before the MSGCTXT_SEPARATOR is the msgctxt.  */
              *separator = '\0';
              msgctxt = msgid;
              msgid = separator + 1;
              msgid_len -= msgid - msgctxt;
            }
          else
            msgctxt = NULL;

          /* Read the msgstr.  */
          msgstr = get_string (&bf, header.trans_tab_offset + i * 8,
                               &msgstr_len);

          mp = message_alloc (msgctxt,
                              msgid,
                              (strlen (msgid) + 1 < msgid_len
                               ? msgid + strlen (msgid) + 1
                               : NULL),
                              msgstr, msgstr_len,
                              &pos);
          message_list_append (mlp, mp);
        }

      switch (header.revision & 0xffff)
        {
        case 0:
          break;
        case 1:
        default:
          /* Fill the header parts that apply to minor revision >= 1.  */
          header.n_sysdep_segments = GET_HEADER_FIELD (n_sysdep_segments);
          header.sysdep_segments_offset =
            GET_HEADER_FIELD (sysdep_segments_offset);
          header.n_sysdep_strings = GET_HEADER_FIELD (n_sysdep_strings);
          header.orig_sysdep_tab_offset =
            GET_HEADER_FIELD (orig_sysdep_tab_offset);
          header.trans_sysdep_tab_offset =
            GET_HEADER_FIELD (trans_sysdep_tab_offset);

          for (i = 0; i < header.n_sysdep_strings; i++)
            {
              message_ty *mp;
              char *msgctxt;
              char *msgid;
              size_t msgid_len;
              char *separator;
              char *msgstr;
              size_t msgstr_len;
              nls_uint32 offset;
              size_t f;

              /* Read the msgctxt and msgid.  */
              offset = get_uint32 (&bf, header.orig_sysdep_tab_offset + i * 4);
              msgid = get_sysdep_string (&bf, offset, &header, &msgid_len);
              /* Split into msgctxt and msgid.  */
              separator = strchr (msgid, MSGCTXT_SEPARATOR);
              if (separator != NULL)
                {
                  /* The part before the MSGCTXT_SEPARATOR is the msgctxt.  */
                  *separator = '\0';
                  msgctxt = msgid;
                  msgid = separator + 1;
                  msgid_len -= msgid - msgctxt;
                }
              else
                msgctxt = NULL;

              /* Read the msgstr.  */
              offset = get_uint32 (&bf, header.trans_sysdep_tab_offset + i * 4);
              msgstr = get_sysdep_string (&bf, offset, &header, &msgstr_len);

              mp = message_alloc (msgctxt,
                                  msgid,
                                  (strlen (msgid) + 1 < msgid_len
                                   ? msgid + strlen (msgid) + 1
                                   : NULL),
                                  msgstr, msgstr_len,
                                  &pos);

              /* Only messages with c-format or objc-format annotation are
                 recognized as having system-dependent strings by msgfmt.
                 Which one of the two, we don't know.  We have to guess,
                 assuming that c-format is more probable than objc-format and
                 that the .mo was likely produced by "msgfmt -c".  */
              for (f = format_c; ; f = format_objc)
                {
                  bool valid = true;
                  struct formatstring_parser *parser = formatstring_parsers[f];
                  const char *str_end;
                  const char *str;

                  str_end = msgid + msgid_len;
                  for (str = msgid; str < str_end; str += strlen (str) + 1)
                    {
                      char *invalid_reason = NULL;
                      void *descr =
                        parser->parse (str, false, NULL, &invalid_reason);

                      if (descr != NULL)
                        parser->free (descr);
                      else
                        {
                          free (invalid_reason);
                          valid = false;
                          break;
                        }
                    }
                  if (valid)
                    {
                      str_end = msgstr + msgstr_len;
                      for (str = msgstr; str < str_end; str += strlen (str) + 1)
                        {
                          char *invalid_reason = NULL;
                          void *descr =
                            parser->parse (str, true, NULL, &invalid_reason);

                          if (descr != NULL)
                            parser->free (descr);
                          else
                            {
                              free (invalid_reason);
                              valid = false;
                              break;
                            }
                        }
                    }

                  if (valid)
                    {
                      /* Found the most likely among c-format, objc-format.  */
                      mp->is_format[f] = yes;
                      break;
                    }

                  /* Try next f.  */
                  if (f == format_objc)
                    break;
                }

              message_list_append (mlp, mp);
            }
          break;
        }
      break;

    default:
      goto unrecognised;
    }

  if (fp != stdin)
    fclose (fp);
}
Exemple #12
0
void
erts_queue_dist_message(Process *rcvr,
			ErtsProcLocks *rcvr_locks,
			ErtsDistExternal *dist_ext,
			Eterm token)
{
    ErlMessage* mp;
#ifdef ERTS_SMP
    ErtsProcLocks need_locks;
#endif

    ERTS_SMP_LC_ASSERT(*rcvr_locks == erts_proc_lc_my_proc_locks(rcvr));

    mp = message_alloc();

#ifdef ERTS_SMP
    need_locks = ~(*rcvr_locks) & (ERTS_PROC_LOCK_MSGQ|ERTS_PROC_LOCK_STATUS);
    if (need_locks) {
	*rcvr_locks |= need_locks;
	if (erts_smp_proc_trylock(rcvr, need_locks) == EBUSY) {
	    if (need_locks == ERTS_PROC_LOCK_MSGQ) {
		erts_smp_proc_unlock(rcvr, ERTS_PROC_LOCK_STATUS);
		need_locks = (ERTS_PROC_LOCK_MSGQ
			      | ERTS_PROC_LOCK_STATUS);
	    }
	    erts_smp_proc_lock(rcvr, need_locks);
	}
    }

    if (rcvr->is_exiting || ERTS_PROC_PENDING_EXIT(rcvr)) {
	/* Drop message if receiver is exiting or has a pending exit ... */
	if (is_not_nil(token)) {
	    ErlHeapFragment *heap_frag;
	    heap_frag = erts_dist_ext_trailer(mp->data.dist_ext);
	    erts_cleanup_offheap(&heap_frag->off_heap);
	}
	erts_free_dist_ext_copy(dist_ext);
	message_free(mp);
    }
    else
#endif
    if (IS_TRACED_FL(rcvr, F_TRACE_RECEIVE)) {
	/* Ahh... need to decode it in order to trace it... */
	ErlHeapFragment *mbuf;
	Eterm msg;
	message_free(mp);
	msg = erts_msg_distext2heap(rcvr, rcvr_locks, &mbuf, &token, dist_ext);
	if (is_value(msg))
	    erts_queue_message(rcvr, rcvr_locks, mbuf, msg, token);
    }
    else {
	/* Enqueue message on external format */

	ERL_MESSAGE_TERM(mp) = THE_NON_VALUE;
	ERL_MESSAGE_TOKEN(mp) = token;
	mp->next = NULL;

	mp->data.dist_ext = dist_ext;
	LINK_MESSAGE(rcvr, mp);

	notify_new_message(rcvr);
    }
}
Exemple #13
0
/* Add a message last in message queue */
void
erts_queue_message(Process* receiver,
		   ErtsProcLocks *receiver_locks,
		   ErlHeapFragment* bp,
		   Eterm message,
		   Eterm seq_trace_token)
{
    ErlMessage* mp;
#ifdef ERTS_SMP
    ErtsProcLocks need_locks;
#else
    ASSERT(bp != NULL || receiver->mbuf == NULL);
#endif

    ERTS_SMP_LC_ASSERT(*receiver_locks == erts_proc_lc_my_proc_locks(receiver));

    mp = message_alloc();

#ifdef ERTS_SMP
    need_locks = ~(*receiver_locks) & (ERTS_PROC_LOCK_MSGQ
				       | ERTS_PROC_LOCK_STATUS);
    if (need_locks) {
	*receiver_locks |= need_locks;
	if (erts_smp_proc_trylock(receiver, need_locks) == EBUSY) {
	    if (need_locks == ERTS_PROC_LOCK_MSGQ) {
		erts_smp_proc_unlock(receiver, ERTS_PROC_LOCK_STATUS);
		need_locks = (ERTS_PROC_LOCK_MSGQ
			      | ERTS_PROC_LOCK_STATUS);
	    }
	    erts_smp_proc_lock(receiver, need_locks);
	}
    }

    if (receiver->is_exiting || ERTS_PROC_PENDING_EXIT(receiver)) {
	/* Drop message if receiver is exiting or has a pending
	 * exit ...
	 */
	if (bp)
	    free_message_buffer(bp);
	message_free(mp);
	return;
    }
#endif

    ERL_MESSAGE_TERM(mp) = message;
    ERL_MESSAGE_TOKEN(mp) = seq_trace_token;
    mp->next = NULL;

#ifdef ERTS_SMP
    if (*receiver_locks & ERTS_PROC_LOCK_MAIN) {
	mp->data.heap_frag = bp;

	/*
	 * We move 'in queue' to 'private queue' and place
	 * message at the end of 'private queue' in order
	 * to ensure that the 'in queue' doesn't contain
	 * references into the heap. By ensuring this,
	 * we don't need to include the 'in queue' in
	 * the root set when garbage collecting.
	 */
	ERTS_SMP_MSGQ_MV_INQ2PRIVQ(receiver);
	LINK_MESSAGE_PRIVQ(receiver, mp);
    }
    else {
	mp->data.heap_frag = bp;
	LINK_MESSAGE(receiver, mp);
    }
#else
    mp->data.heap_frag = bp;
    LINK_MESSAGE(receiver, mp);
#endif

    notify_new_message(receiver);

    if (IS_TRACED_FL(receiver, F_TRACE_RECEIVE)) {
	trace_receive(receiver, message);
    }
    
#ifndef ERTS_SMP
    ERTS_HOLE_CHECK(receiver);
#endif
}
Exemple #14
0
void
erts_send_message(Process* sender,
		  Process* receiver,
		  ErtsProcLocks *receiver_locks,
		  Eterm message,
		  unsigned flags)
{
    Uint msize;
    ErlHeapFragment* bp = NULL;
    Eterm token = NIL;

    BM_STOP_TIMER(system);
    BM_MESSAGE(message,sender,receiver);
    BM_START_TIMER(send);

    if (SEQ_TRACE_TOKEN(sender) != NIL && !(flags & ERTS_SND_FLG_NO_SEQ_TRACE)) {
        Eterm* hp;

        BM_SWAP_TIMER(send,size);
	msize = size_object(message);
        BM_SWAP_TIMER(size,send);

	seq_trace_update_send(sender);
	seq_trace_output(SEQ_TRACE_TOKEN(sender), message, SEQ_TRACE_SEND, 
			 receiver->id, sender);
	bp = new_message_buffer(msize + 6 /* TUPLE5 */);
	hp = bp->mem;

        BM_SWAP_TIMER(send,copy);
	token = copy_struct(SEQ_TRACE_TOKEN(sender),
			    6 /* TUPLE5 */,
			    &hp,
			    &bp->off_heap);

	message = copy_struct(message, msize, &hp, &bp->off_heap);
        BM_MESSAGE_COPIED(msize);
        BM_SWAP_TIMER(copy,send);

        erts_queue_message(receiver,
			   receiver_locks,
			   bp,
			   message,
			   token);
        BM_SWAP_TIMER(send,system);
#ifdef HYBRID
    } else {
        ErlMessage* mp = message_alloc();
        BM_SWAP_TIMER(send,copy);
#ifdef INCREMENTAL
        /* TODO: During GC activate processes if the message relies in
         * the fromspace and the sender is active. During major
         * collections add the message to the gray stack if it relies
         * in the old generation and the sender is active and the
         * receiver is inactive.

        if (!IS_CONST(message) && (ma_gc_flags & GC_CYCLE) &&
            (ptr_val(message) >= inc_fromspc &&
            ptr_val(message) < inc_fromend) && INC_IS_ACTIVE(sender))
            INC_ACTIVATE(receiver);
        else if (!IS_CONST(message) && (ma_gc_flags & GC_CYCLE) &&
            (ptr_val(message) >= global_old_heap &&
            ptr_val(message) < global_old_hend) &&
            INC_IS_ACTIVE(sender) && !INC_IS_ACTIVE(receiver))
            Mark message in blackmap and add it to the gray stack
        */

         if (!IS_CONST(message))
            INC_ACTIVATE(receiver);
#endif
        LAZY_COPY(sender,message);
        BM_SWAP_TIMER(copy,send);
        ERL_MESSAGE_TERM(mp) = message;
        ERL_MESSAGE_TOKEN(mp) = NIL;
        mp->next = NULL;
	LINK_MESSAGE(receiver, mp);
        ACTIVATE(receiver);

        if (receiver->status == P_WAITING) {
            erts_add_to_runq(receiver);
        } else if (receiver->status == P_SUSPENDED) {
            receiver->rstatus = P_RUNABLE;
        }
        if (IS_TRACED_FL(receiver, F_TRACE_RECEIVE)) {
            trace_receive(receiver, message);
        }

        BM_SWAP_TIMER(send,system);
        return;
#else
    } else if (sender == receiver) {
Exemple #15
0
/* Delivers a notification which matches the receiver's subscription
 * expression */
static int
notify_cb(elvin_handle_t handle,
          elvin_subscription_t subscription,
          elvin_notification_t notification,
          int is_secure,
          void *rock,
          elvin_error_t error)
{
    usenet_sub_t self = (usenet_sub_t)rock;
    message_t message;
    char *string;
    char *newsgroups;
    char *name;
    char *subject;
    char *mime_type;
    char *mime_args;
    char *buffer = NULL;
    char *attachment = NULL;
    size_t length = 0;
    int found;

    /* If we don't have a callback than bail out now */
    if (self->callback == NULL) {
        return 1;
    }

    /* Get the newsgroups to which the message was posted */
    if (!elvin_notification_get_string(notification, NEWSGROUPS, &found,
                                       &string, error)) {
        eeprintf(error, "elvin_notification_get_string failed\n");
        exit(1);
    }

    /* Use a reasonable default */
    string = found ? string : "news";

    /* Prepend `usenet:' to the beginning of the group field */
    length = strlen(USENET_PREFIX) + strlen(string) - 1;
    newsgroups = malloc(length);
    if (newsgroups == NULL) {
        return 0;
    }

    snprintf(newsgroups, length, USENET_PREFIX, string);

    /* Get the name from the FROM_NAME field (if provided) */
    if (!elvin_notification_get_string(notification, FROM_NAME, &found, &name,
                                       error)) {
        eeprintf(error, "elvin_notification_get_string failed\n");
        exit(1);
    }

    if (!found) {
        /* No FROM_NAME field, so try FROM_EMAIL */
        if (!elvin_notification_get_string(notification, FROM_EMAIL, &found,
                                           &name, error)) {
            eeprintf(error, "elvin_notification_get_string failed\n");
            exit(1);
        }

        if (!found) {
            /* No FROM_EMAIL, so try FROM */
            if (!elvin_notification_get_string(notification, FROM, &found,
                                               &name, error)) {
                eeprintf(error, "elvin_notification_get_string failed\n");
                exit(1);
            }

            if (!found) {
                /* Give up */
                name = "anonymous";
            }
        }
    }

    /* Get the SUBJECT field (if provided) */
    if (!elvin_notification_get_string(notification, SUBJECT, &found,
                                       &subject, error)) {
        eeprintf(error, "elvin_notification_get_string failed\n");
        exit(1);
    }

    /* Use a default if none found */
    subject = found ? subject : "[no subject]";

    /* Get the MIME_ARGS field (if provided) */
    if (!elvin_notification_get_string(notification, MIME_ARGS, &found,
                                       &mime_args, error)) {
        eeprintf(error, "elvin_notification_get_string failed\n");
        exit(1);
    }

    /* Was the MIME_ARGS field provided? */
    if (found) {
        /* Get the MIME_TYPE field (if provided) */
        if (!elvin_notification_get_string(notification, MIME_TYPE, &found,
                                           &mime_type, error)) {
            eeprintf(error, "elvin_notification_get_string failed\n");
            exit(1);
        }

        /* Use a default if none found */
        mime_type = found ? mime_type : URL_MIME_TYPE;
    } else {
        char *message_id;

        /* No MIME_ARGS.  Look for a message-id */
        if (!elvin_notification_get_string(notification, MESSAGE_ID, &found,
                                           &message_id, error)) {
            eeprintf(error, "elvin_notification_get_string failed\n");
            exit(1);
        }

        if (found) {
            char *news_host;

            /* Look up the news host field */
            if (!elvin_notification_get_string(
                    notification,
                    X_NNTP_HOST,
                    &found, &news_host,
                    error)) {
                eeprintf(error, "elvin_notification_get_string failed\n");
                exit(1);
            }

            news_host = found ? news_host : "news";

            length = strlen(NEWS_URL) + strlen(news_host) +
                strlen(message_id) - 3;
            buffer = malloc(length);
            if (buffer == NULL) {
                mime_type = NULL;
                mime_args = NULL;
            } else {
                snprintf(buffer, length, NEWS_URL, news_host, message_id);
                mime_args = buffer;
                mime_type = NEWS_MIME_TYPE;
            }
        } else {
            mime_type = NULL;
            mime_args = NULL;
        }
    }

    /* Convert the mime type and args into an attachment */
    if (mime_type == NULL || mime_args == NULL) {
        attachment = NULL;
        length = 0;
    } else {
        length = strlen(ATTACHMENT_FMT) - 4 + strlen(mime_type) + strlen(
            mime_args);
        attachment = malloc(length + 1);
        if (attachment == NULL) {
            length = 0;
        } else {
            snprintf(attachment, length + 1, ATTACHMENT_FMT,
                     mime_type, mime_args);
        }
    }

    /* Construct a message out of all of that */
    message = message_alloc(NULL, newsgroups, name, subject, 60,
                            attachment, length,
                            NULL, NULL, NULL, NULL);
    if (message != NULL) {
        /* Deliver the message */
        self->callback(self->rock, message, False);
    }

    /* Clean up */
    free(newsgroups);
    if (buffer != NULL) {
        free(buffer);
    }

    return 1;
}
Exemple #16
0
Sint
erts_send_message(Process* sender,
		  Process* receiver,
		  ErtsProcLocks *receiver_locks,
		  Eterm message,
		  unsigned flags)
{
    Uint msize;
    ErlHeapFragment* bp = NULL;
    Eterm token = NIL;
    Sint res = 0;
#ifdef USE_VM_PROBES
    DTRACE_CHARBUF(sender_name, 64);
    DTRACE_CHARBUF(receiver_name, 64);
    Sint tok_label = 0;
    Sint tok_lastcnt = 0;
    Sint tok_serial = 0;
#endif
    BM_STOP_TIMER(system);
    BM_MESSAGE(message,sender,receiver);
    BM_START_TIMER(send);

 #ifdef USE_VM_PROBES
    *sender_name = *receiver_name = '\0';
   if (DTRACE_ENABLED(message_send)) {
        erts_snprintf(sender_name, sizeof(DTRACE_CHARBUF_NAME(sender_name)),
		      "%T", sender->common.id);
        erts_snprintf(receiver_name, sizeof(DTRACE_CHARBUF_NAME(receiver_name)),
		      "%T", receiver->common.id);
    }
#endif
    if (SEQ_TRACE_TOKEN(sender) != NIL && !(flags & ERTS_SND_FLG_NO_SEQ_TRACE)) {
        Eterm* hp;
	Eterm stoken = SEQ_TRACE_TOKEN(sender);
	Uint seq_trace_size = 0;
#ifdef USE_VM_PROBES
	Uint dt_utag_size = 0;
	Eterm utag = NIL;
#endif

	BM_SWAP_TIMER(send,size);
	msize = size_object(message);
	BM_SWAP_TIMER(size,send);

#ifdef USE_VM_PROBES
	if (stoken != am_have_dt_utag) {
#endif

	    seq_trace_update_send(sender);
	    seq_trace_output(stoken, message, SEQ_TRACE_SEND, 
			     receiver->common.id, sender);
	    seq_trace_size = 6; /* TUPLE5 */
#ifdef USE_VM_PROBES
	}
	if (DT_UTAG_FLAGS(sender) & DT_UTAG_SPREADING) {
	    dt_utag_size = size_object(DT_UTAG(sender));
	} else if (stoken == am_have_dt_utag ) {
	    stoken = NIL;
	}
#endif

	bp = new_message_buffer(msize + seq_trace_size 
#ifdef USE_VM_PROBES
				+ dt_utag_size
#endif
				);
	hp = bp->mem;

        BM_SWAP_TIMER(send,copy);
	token = copy_struct(stoken,
			    seq_trace_size,
			    &hp,
			    &bp->off_heap);

	message = copy_struct(message, msize, &hp, &bp->off_heap);
#ifdef USE_VM_PROBES
	if (DT_UTAG_FLAGS(sender) & DT_UTAG_SPREADING) {
	    utag = copy_struct(DT_UTAG(sender), dt_utag_size, &hp, &bp->off_heap);
#ifdef DTRACE_TAG_HARDDEBUG
	    erts_fprintf(stderr,
			 "Dtrace -> (%T) Spreading tag (%T) with "
			 "message %T!\r\n",sender->common.id, utag, message);
#endif
	}
#endif
        BM_MESSAGE_COPIED(msize);
        BM_SWAP_TIMER(copy,send);

#ifdef USE_VM_PROBES
        if (DTRACE_ENABLED(message_send)) {
	    if (stoken != NIL && stoken != am_have_dt_utag) {
		tok_label = signed_val(SEQ_TRACE_T_LABEL(stoken));
		tok_lastcnt = signed_val(SEQ_TRACE_T_LASTCNT(stoken));
		tok_serial = signed_val(SEQ_TRACE_T_SERIAL(stoken));
	    }
	    DTRACE6(message_send, sender_name, receiver_name,
		    msize, tok_label, tok_lastcnt, tok_serial);
        }
#endif
        res = queue_message(NULL,
			    receiver,
			    receiver_locks,
			    NULL,
			    bp,
			    message,
			    token
#ifdef USE_VM_PROBES
			    , utag
#endif
	    );
        BM_SWAP_TIMER(send,system);
    } else if (sender == receiver) {
	/* Drop message if receiver has a pending exit ... */
#ifdef ERTS_SMP
	ErtsProcLocks need_locks = (~(*receiver_locks)
				    & (ERTS_PROC_LOCK_MSGQ
				       | ERTS_PROC_LOCK_STATUS));
	if (need_locks) {
	    *receiver_locks |= need_locks;
	    if (erts_smp_proc_trylock(receiver, need_locks) == EBUSY) {
		if (need_locks == ERTS_PROC_LOCK_MSGQ) {
		    erts_smp_proc_unlock(receiver, ERTS_PROC_LOCK_STATUS);
		    need_locks = ERTS_PROC_LOCK_MSGQ|ERTS_PROC_LOCK_STATUS;
		}
		erts_smp_proc_lock(receiver, need_locks);
	    }
	}
	if (!ERTS_PROC_PENDING_EXIT(receiver))
#endif
	{
	    ErlMessage* mp = message_alloc();

            DTRACE6(message_send, sender_name, receiver_name,
                    size_object(message), tok_label, tok_lastcnt, tok_serial);
	    mp->data.attached = NULL;
	    ERL_MESSAGE_TERM(mp) = message;
	    ERL_MESSAGE_TOKEN(mp) = NIL;
#ifdef USE_VM_PROBES
	    ERL_MESSAGE_DT_UTAG(mp) = NIL;
#endif
	    mp->next = NULL;
	    /*
	     * We move 'in queue' to 'private queue' and place
	     * message at the end of 'private queue' in order
	     * to ensure that the 'in queue' doesn't contain
	     * references into the heap. By ensuring this,
	     * we don't need to include the 'in queue' in
	     * the root set when garbage collecting.
	     */
	    
	    ERTS_SMP_MSGQ_MV_INQ2PRIVQ(receiver);
	    LINK_MESSAGE_PRIVQ(receiver, mp);

	    res = receiver->msg.len;

	    if (IS_TRACED_FL(receiver, F_TRACE_RECEIVE)) {
		trace_receive(receiver, message);
	    }
	}
        BM_SWAP_TIMER(send,system);
    } else {
	ErlOffHeap *ohp;
        Eterm *hp;
	erts_aint32_t state;

	BM_SWAP_TIMER(send,size);
	msize = size_object(message);
	BM_SWAP_TIMER(size,send);
	hp = erts_alloc_message_heap_state(msize,
					   &bp,
					   &ohp,
					   receiver,
					   receiver_locks,
					   &state);
	BM_SWAP_TIMER(send,copy);
	message = copy_struct(message, msize, &hp, ohp);
	BM_MESSAGE_COPIED(msz);
	BM_SWAP_TIMER(copy,send);
        DTRACE6(message_send, sender_name, receiver_name,
                msize, tok_label, tok_lastcnt, tok_serial);
	res = queue_message(sender,
			    receiver,
			    receiver_locks,
			    &state,
			    bp,
			    message,
			    token
#ifdef USE_VM_PROBES
			    , NIL
#endif
	    );
        BM_SWAP_TIMER(send,system);
    }
   return res;
}
Exemple #17
0
/* Add a message last in message queue */
static Sint
queue_message(Process *c_p,
	      Process* receiver,
	      ErtsProcLocks *receiver_locks,
	      erts_aint32_t *receiver_state,
	      ErlHeapFragment* bp,
	      Eterm message,
	      Eterm seq_trace_token
#ifdef USE_VM_PROBES
		   , Eterm dt_utag
#endif
    )
{
    Sint res;
    ErlMessage* mp;
    int locked_msgq = 0;
    erts_aint_t state;

#ifndef ERTS_SMP
    ASSERT(bp != NULL || receiver->mbuf == NULL);
#endif

    ERTS_SMP_LC_ASSERT(*receiver_locks == erts_proc_lc_my_proc_locks(receiver));

    mp = message_alloc();

    if (receiver_state)
	state = *receiver_state;
    else
	state = erts_smp_atomic32_read_acqb(&receiver->state);

#ifdef ERTS_SMP

    if (state & (ERTS_PSFLG_EXITING|ERTS_PSFLG_PENDING_EXIT))
	goto exiting;

    if (!(*receiver_locks & ERTS_PROC_LOCK_MSGQ)) {
	if (erts_smp_proc_trylock(receiver, ERTS_PROC_LOCK_MSGQ) == EBUSY) {
	    ErtsProcLocks need_locks = ERTS_PROC_LOCK_MSGQ;
	    if (*receiver_locks & ERTS_PROC_LOCK_STATUS) {
		erts_smp_proc_unlock(receiver, ERTS_PROC_LOCK_STATUS);
		need_locks |= ERTS_PROC_LOCK_STATUS;
	    }
	    erts_smp_proc_lock(receiver, need_locks);
	}
	locked_msgq = 1;
	state = erts_smp_atomic32_read_nob(&receiver->state);
	if (receiver_state)
	    *receiver_state = state;
    }

#endif

    if (state & (ERTS_PSFLG_PENDING_EXIT|ERTS_PSFLG_EXITING)) {
#ifdef ERTS_SMP
    exiting:
#endif
	/* Drop message if receiver is exiting or has a pending exit... */
	if (locked_msgq)
	    erts_smp_proc_unlock(receiver, ERTS_PROC_LOCK_MSGQ);
	if (bp)
	    free_message_buffer(bp);
	message_free(mp);
	return 0;
    }

    ERL_MESSAGE_TERM(mp) = message;
    ERL_MESSAGE_TOKEN(mp) = seq_trace_token;
#ifdef USE_VM_PROBES
    ERL_MESSAGE_DT_UTAG(mp) = dt_utag;
#endif
    mp->next = NULL;
    mp->data.heap_frag = bp;

#ifndef ERTS_SMP
    res = receiver->msg.len;
#else
    res = receiver->msg_inq.len;
    if (*receiver_locks & ERTS_PROC_LOCK_MAIN) {
	/*
	 * We move 'in queue' to 'private queue' and place
	 * message at the end of 'private queue' in order
	 * to ensure that the 'in queue' doesn't contain
	 * references into the heap. By ensuring this,
	 * we don't need to include the 'in queue' in
	 * the root set when garbage collecting.
	 */
	res += receiver->msg.len;
	ERTS_SMP_MSGQ_MV_INQ2PRIVQ(receiver);
	LINK_MESSAGE_PRIVQ(receiver, mp);
    }
    else
#endif
    {
	LINK_MESSAGE(receiver, mp);
    }

#ifdef USE_VM_PROBES
    if (DTRACE_ENABLED(message_queued)) {
        DTRACE_CHARBUF(receiver_name, DTRACE_TERM_BUF_SIZE);
        Sint tok_label = 0;
        Sint tok_lastcnt = 0;
        Sint tok_serial = 0;

        dtrace_proc_str(receiver, receiver_name);
        if (seq_trace_token != NIL && is_tuple(seq_trace_token)) {
            tok_label = signed_val(SEQ_TRACE_T_LABEL(seq_trace_token));
            tok_lastcnt = signed_val(SEQ_TRACE_T_LASTCNT(seq_trace_token));
            tok_serial = signed_val(SEQ_TRACE_T_SERIAL(seq_trace_token));
        }
        DTRACE6(message_queued,
                receiver_name, size_object(message), receiver->msg.len,
                tok_label, tok_lastcnt, tok_serial);
    }
#endif

    if (IS_TRACED_FL(receiver, F_TRACE_RECEIVE))
	trace_receive(receiver, message);

    if (locked_msgq)
	erts_smp_proc_unlock(receiver, ERTS_PROC_LOCK_MSGQ);

    erts_proc_notify_new_message(receiver,
#ifdef ERTS_SMP
				 *receiver_locks
#else
				 0
#endif
	);

#ifndef ERTS_SMP
    ERTS_HOLE_CHECK(receiver);
#endif
    return res;
}
Exemple #18
0
void
erts_queue_dist_message(Process *rcvr,
			ErtsProcLocks *rcvr_locks,
			ErtsDistExternal *dist_ext,
			Eterm token)
{
    ErlMessage* mp;
#ifdef USE_VM_PROBES
    Sint tok_label = 0;
    Sint tok_lastcnt = 0;
    Sint tok_serial = 0;
#endif
#ifdef ERTS_SMP
    erts_aint_t state;
#endif

    ERTS_SMP_LC_ASSERT(*rcvr_locks == erts_proc_lc_my_proc_locks(rcvr));

    mp = message_alloc();

#ifdef ERTS_SMP
    if (!(*rcvr_locks & ERTS_PROC_LOCK_MSGQ)) {
	if (erts_smp_proc_trylock(rcvr, ERTS_PROC_LOCK_MSGQ) == EBUSY) {
	    ErtsProcLocks need_locks = ERTS_PROC_LOCK_MSGQ;
	    if (*rcvr_locks & ERTS_PROC_LOCK_STATUS) {
		erts_smp_proc_unlock(rcvr, ERTS_PROC_LOCK_STATUS);
		need_locks |= ERTS_PROC_LOCK_STATUS;
	    }
	    erts_smp_proc_lock(rcvr, need_locks);
	}
    }

    state = erts_smp_atomic32_read_acqb(&rcvr->state);
    if (state & (ERTS_PSFLG_PENDING_EXIT|ERTS_PSFLG_EXITING)) {
	if (!(*rcvr_locks & ERTS_PROC_LOCK_MSGQ))
	    erts_smp_proc_unlock(rcvr, ERTS_PROC_LOCK_MSGQ);
	/* Drop message if receiver is exiting or has a pending exit ... */
	if (is_not_nil(token)) {
	    ErlHeapFragment *heap_frag;
	    heap_frag = erts_dist_ext_trailer(mp->data.dist_ext);
	    erts_cleanup_offheap(&heap_frag->off_heap);
	}
	erts_free_dist_ext_copy(dist_ext);
	message_free(mp);
    }
    else
#endif
    if (IS_TRACED_FL(rcvr, F_TRACE_RECEIVE)) {
	/* Ahh... need to decode it in order to trace it... */
	ErlHeapFragment *mbuf;
	Eterm msg;
	if (!(*rcvr_locks & ERTS_PROC_LOCK_MSGQ))
	    erts_smp_proc_unlock(rcvr, ERTS_PROC_LOCK_MSGQ);
	message_free(mp);
	msg = erts_msg_distext2heap(rcvr, rcvr_locks, &mbuf, &token, dist_ext);
	if (is_value(msg))
#ifdef USE_VM_PROBES
            if (DTRACE_ENABLED(message_queued)) {
                DTRACE_CHARBUF(receiver_name, DTRACE_TERM_BUF_SIZE);

                dtrace_proc_str(rcvr, receiver_name);
                if (token != NIL && token != am_have_dt_utag) {
                    tok_label = signed_val(SEQ_TRACE_T_LABEL(token));
                    tok_lastcnt = signed_val(SEQ_TRACE_T_LASTCNT(token));
                    tok_serial = signed_val(SEQ_TRACE_T_SERIAL(token));
                }
                DTRACE6(message_queued,
                        receiver_name, size_object(msg), rcvr->msg.len,
                        tok_label, tok_lastcnt, tok_serial);
            }
#endif
	    erts_queue_message(rcvr, rcvr_locks, mbuf, msg, token);
    }
    else {
	/* Enqueue message on external format */

	ERL_MESSAGE_TERM(mp) = THE_NON_VALUE;
#ifdef USE_VM_PROBES
	ERL_MESSAGE_DT_UTAG(mp) = NIL;
	if (token == am_have_dt_utag) {
	    ERL_MESSAGE_TOKEN(mp) = NIL;
	} else {
#endif
	    ERL_MESSAGE_TOKEN(mp) = token;
#ifdef USE_VM_PROBES
	}
#endif
	mp->next = NULL;

#ifdef USE_VM_PROBES
        if (DTRACE_ENABLED(message_queued)) {
            DTRACE_CHARBUF(receiver_name, DTRACE_TERM_BUF_SIZE);

            dtrace_proc_str(rcvr, receiver_name);
            if (token != NIL && token != am_have_dt_utag) {
                tok_label = signed_val(SEQ_TRACE_T_LABEL(token));
                tok_lastcnt = signed_val(SEQ_TRACE_T_LASTCNT(token));
                tok_serial = signed_val(SEQ_TRACE_T_SERIAL(token));
            }
            /*
             * TODO: We don't know the real size of the external message here.
             *       -1 will appear to a D script as 4294967295.
             */
            DTRACE6(message_queued, receiver_name, -1, rcvr->msg.len + 1,
                    tok_label, tok_lastcnt, tok_serial);
        }
#endif
	mp->data.dist_ext = dist_ext;
	LINK_MESSAGE(rcvr, mp);

	if (!(*rcvr_locks & ERTS_PROC_LOCK_MSGQ))
	    erts_smp_proc_unlock(rcvr, ERTS_PROC_LOCK_MSGQ);

	erts_proc_notify_new_message(rcvr,
#ifdef ERTS_SMP
				     *rcvr_locks
#else
				     0
#endif
	    );
    }
}
Exemple #19
0
/* Add a message last in message queue */
void
erts_queue_message(Process* receiver,
                   ErtsProcLocks *receiver_locks,
                   ErlHeapFragment* bp,
                   Eterm message,
                   Eterm seq_trace_token
#ifdef USE_VM_PROBES
                   , Eterm dt_utag
#endif
                  )
{
    ErlMessage* mp;
#ifdef ERTS_SMP
    ErtsProcLocks need_locks;
#else
    ASSERT(bp != NULL || receiver->mbuf == NULL);
#endif

    ERTS_SMP_LC_ASSERT(*receiver_locks == erts_proc_lc_my_proc_locks(receiver));

    mp = message_alloc();

#ifdef ERTS_SMP
    need_locks = ~(*receiver_locks) & (ERTS_PROC_LOCK_MSGQ
                                       | ERTS_PROC_LOCK_STATUS);
    if (need_locks) {
        *receiver_locks |= need_locks;
        if (erts_smp_proc_trylock(receiver, need_locks) == EBUSY) {
            if (need_locks == ERTS_PROC_LOCK_MSGQ) {
                erts_smp_proc_unlock(receiver, ERTS_PROC_LOCK_STATUS);
                need_locks = (ERTS_PROC_LOCK_MSGQ
                              | ERTS_PROC_LOCK_STATUS);
            }
            erts_smp_proc_lock(receiver, need_locks);
        }
    }

    if (receiver->is_exiting || ERTS_PROC_PENDING_EXIT(receiver)) {
        /* Drop message if receiver is exiting or has a pending
         * exit ...
         */
        if (bp)
            free_message_buffer(bp);
        message_free(mp);
        return;
    }
#endif

    ERL_MESSAGE_TERM(mp) = message;
    ERL_MESSAGE_TOKEN(mp) = seq_trace_token;
#ifdef USE_VM_PROBES
    ERL_MESSAGE_DT_UTAG(mp) = dt_utag;
#endif
    mp->next = NULL;
    mp->data.heap_frag = bp;

#ifdef ERTS_SMP
    if (*receiver_locks & ERTS_PROC_LOCK_MAIN) {
        /*
         * We move 'in queue' to 'private queue' and place
         * message at the end of 'private queue' in order
         * to ensure that the 'in queue' doesn't contain
         * references into the heap. By ensuring this,
         * we don't need to include the 'in queue' in
         * the root set when garbage collecting.
         */
        ERTS_SMP_MSGQ_MV_INQ2PRIVQ(receiver);
        LINK_MESSAGE_PRIVQ(receiver, mp);
    }
    else {
        LINK_MESSAGE(receiver, mp);
    }
#else
    LINK_MESSAGE(receiver, mp);
#endif

#ifdef USE_VM_PROBES
    if (DTRACE_ENABLED(message_queued)) {
        DTRACE_CHARBUF(receiver_name, DTRACE_TERM_BUF_SIZE);
        Sint tok_label = 0;
        Sint tok_lastcnt = 0;
        Sint tok_serial = 0;

        dtrace_proc_str(receiver, receiver_name);
        if (seq_trace_token != NIL && is_tuple(seq_trace_token)) {
            tok_label = signed_val(SEQ_TRACE_T_LABEL(seq_trace_token));
            tok_lastcnt = signed_val(SEQ_TRACE_T_LASTCNT(seq_trace_token));
            tok_serial = signed_val(SEQ_TRACE_T_SERIAL(seq_trace_token));
        }
        DTRACE6(message_queued,
                receiver_name, size_object(message), receiver->msg.len,
                tok_label, tok_lastcnt, tok_serial);
    }
#endif
    notify_new_message(receiver);

    if (IS_TRACED_FL(receiver, F_TRACE_RECEIVE)) {
        trace_receive(receiver, message);
    }

#ifndef ERTS_SMP
    ERTS_HOLE_CHECK(receiver);
#endif
}