int
__go_empty_interface_compare (struct __go_empty_interface left,
			      struct __go_empty_interface right)
{
  const struct __go_type_descriptor *left_descriptor;

  left_descriptor = left.__type_descriptor;

  if (((uintptr_t) left_descriptor & reflectFlags) != 0
      || ((uintptr_t) right.__type_descriptor & reflectFlags) != 0)
    __go_panic_msg ("invalid interface value");

  if (left_descriptor == NULL && right.__type_descriptor == NULL)
    return 0;
  if (left_descriptor == NULL || right.__type_descriptor == NULL)
    return 1;
  if (!__go_type_descriptors_equal (left_descriptor,
				    right.__type_descriptor))
    return 1;
  if (__go_is_pointer_type (left_descriptor))
    return left.__object == right.__object ? 0 : 1;
  if (!left_descriptor->__equalfn (left.__object, right.__object,
				   left_descriptor->__size))
    return 1;
  return 0;
}
示例#2
0
uint64_t
__go_receive_small_closed (struct __go_channel *channel, _Bool for_select,
                           _Bool *received)
{
    uintptr_t element_size;
    uint64_t ret;

    if (channel == NULL)
        __go_panic_msg ("receive from nil channel");

    element_size = channel->element_type->__size;
    __go_assert (element_size <= sizeof (uint64_t));

    if (!__go_receive_acquire (channel, for_select))
    {
        if (received != NULL)
            *received = 0;
        return 0;
    }

    ret = channel->data[channel->next_fetch];

    __go_receive_release (channel);

    if (received != NULL)
        *received = 1;

    return ret;
}
void
__go_builtin_close (struct __go_channel *channel)
{
  int i;

  i = pthread_mutex_lock (&channel->lock);
  __go_assert (i == 0);

  while (channel->selected_for_send)
    {
      i = pthread_cond_wait (&channel->cond, &channel->lock);
      __go_assert (i == 0);
    }

  if (channel->is_closed)
    {
      i = pthread_mutex_unlock (&channel->lock);
      __go_assert (i == 0);
      __go_panic_msg ("close of closed channel");
    }

  channel->is_closed = 1;

  i = pthread_cond_broadcast (&channel->cond);
  __go_assert (i == 0);

  __go_unlock_and_notify_selects (channel);
}
void
__go_runtime_error (int i)
{
  switch (i)
    {
    case SLICE_INDEX_OUT_OF_BOUNDS:
    case ARRAY_INDEX_OUT_OF_BOUNDS:
    case STRING_INDEX_OUT_OF_BOUNDS:
      __go_panic_msg ("index out of range");

    case SLICE_SLICE_OUT_OF_BOUNDS:
    case ARRAY_SLICE_OUT_OF_BOUNDS:
    case STRING_SLICE_OUT_OF_BOUNDS:
      __go_panic_msg ("slice bounds out of range");

    case NIL_DEREFERENCE:
      __go_panic_msg ("nil pointer dereference");

    case MAKE_SLICE_OUT_OF_BOUNDS:
      __go_panic_msg ("make slice len or cap out of range");

    case MAKE_MAP_OUT_OF_BOUNDS:
      __go_panic_msg ("make map len out of range");

    case MAKE_CHAN_OUT_OF_BOUNDS:
      __go_panic_msg ("make chan len out of range");

    default:
      __go_panic_msg ("unknown runtime error");
    }
}
void
__go_send_acquire (struct __go_channel *channel, _Bool for_select)
{
  int i;

  i = pthread_mutex_lock (&channel->lock);
  __go_assert (i == 0);

  while (1)
    {
      if (channel->is_closed)
	{
	  if (for_select)
	    channel->selected_for_send = 0;
	  i = pthread_mutex_unlock (&channel->lock);
	  __go_assert (i == 0);
	  __go_panic_msg ("send on closed channel");
	}

      /* If somebody else has the channel locked for sending, we have
	 to wait.  If FOR_SELECT is true, then we are the one with the
	 lock.  */
      if (!channel->selected_for_send || for_select)
	{
	  if (channel->num_entries == 0)
	    {
	      /* This is a synchronous channel.  If nobody else is
		 waiting to send, we grab the channel and tell the
		 caller to send the data.  We will then wait for a
		 receiver.  */
	      if (!channel->waiting_to_send)
		{
		  __go_assert (channel->next_store == 0);
		  return;
		}
	    }
	  else
	    {
	      /* If there is room on the channel, we are OK.  */
	      if ((channel->next_store + 1) % channel->num_entries
		  != channel->next_fetch)
		return;
	    }
	}

      /* Wait for something to change, then loop around and try
	 again.  */

      i = pthread_cond_wait (&channel->cond, &channel->lock);
      __go_assert (i == 0);
    }
}
示例#6
0
void
__go_send_small (struct __go_channel *channel, uint64_t val, _Bool for_select)
{
  if (channel == NULL)
    __go_panic_msg ("send to nil channel");

  __go_assert (channel->element_size <= sizeof (uint64_t));

  __go_send_acquire (channel, for_select);

  channel->data[channel->next_store] = val;

  __go_send_release (channel);
}
struct __go_string
__go_string_slice (struct __go_string s, int start, int end)
{
  int len;
  struct __go_string ret;

  len = s.__length;
  if (end == -1)
    end = len;
  if (start > len || end < start || end > len)
    __go_panic_msg ("string index out of bounds");
  ret.__data = s.__data + start;
  ret.__length = end - start;
  return ret;
}
示例#8
0
void
__go_send_big (struct __go_channel* channel, const void *val, _Bool for_select)
{
  uintptr_t element_size;
  size_t alloc_size;
  size_t offset;

  if (channel == NULL)
    __go_panic_msg ("send to nil channel");

  element_size = channel->element_type->__size;
  alloc_size = (element_size + sizeof (uint64_t) - 1) / sizeof (uint64_t);

  __go_send_acquire (channel, for_select);

  offset = channel->next_store * alloc_size;
  __builtin_memcpy (&channel->data[offset], val, element_size);

  __go_send_release (channel);
}
示例#9
0
struct __go_map *
__go_new_map (const struct __go_map_descriptor *descriptor, uintptr_t entries)
{
  struct __go_map *ret;

  if ((uintptr_t) (int) entries != entries)
    __go_panic_msg ("map size out of range");

  if (entries == 0)
    entries = 5;
  else
    entries = __go_map_next_prime (entries);
  ret = (struct __go_map *) __go_alloc (sizeof (struct __go_map));
  ret->__descriptor = descriptor;
  ret->__element_count = 0;
  ret->__bucket_count = entries;
  ret->__buckets = (void **) __go_alloc (entries * sizeof (void *));
  __builtin_memset (ret->__buckets, 0, entries * sizeof (void *));
  return ret;
}
void
mapassign (struct __go_map_type *mt, uintptr_t m, uintptr_t key_i,
	   uintptr_t val_i, _Bool pres)
{
  struct __go_map *map = (struct __go_map *) m;
  const struct __go_type_descriptor *key_descriptor;
  void *key;

  __go_assert (mt->__common.__code == GO_MAP);

  if (map == NULL)
    __go_panic_msg ("assignment to entry in nil map");

  key_descriptor = mt->__key_type;
  if (__go_is_pointer_type (key_descriptor))
    key = &key_i;
  else
    key = (void *) key_i;

  if (!pres)
    __go_map_delete (map, key);
  else
    {
      void *p;
      const struct __go_type_descriptor *val_descriptor;
      void *pv;

      p = __go_map_index (map, key, 1);

      val_descriptor = mt->__val_type;
      if (__go_is_pointer_type (val_descriptor))
	pv = &val_i;
      else
	pv = (void *) val_i;
      __builtin_memcpy (p, pv, val_descriptor->__size);
    }
}
_Bool
__go_send_nonblocking_acquire (struct __go_channel *channel)
{
  int i;
  _Bool has_space;

  i = pthread_mutex_lock (&channel->lock);
  __go_assert (i == 0);

  while (channel->selected_for_send)
    {
      i = pthread_cond_wait (&channel->cond, &channel->lock);
      __go_assert (i == 0);
    }

  if (channel->is_closed)
    {
      i = pthread_mutex_unlock (&channel->lock);
      __go_assert (i == 0);
      __go_panic_msg ("send on closed channel");
    }

  if (channel->num_entries > 0)
      has_space = ((channel->next_store + 1) % channel->num_entries
		   != channel->next_fetch);
  else
    {
      /* This is a synchronous channel.  If somebody is current
	 sending, then we can't send.  Otherwise, see if somebody is
	 waiting to receive, or see if we can synch with a select.  */
      if (channel->waiting_to_send)
	{
	  /* Some other goroutine is currently sending on this
	     channel, which means that we can't.  */
	  has_space = 0;
	}
      else if (channel->waiting_to_receive)
	{
	  /* Some other goroutine is waiting to receive a value, so we
	     can send directly to them.  */
	  has_space = 1;
	}
      else if (__go_synch_with_select (channel, 1))
	{
	  /* We found a select waiting to receive data, so we can send
	     to that.  */
	  __go_broadcast_to_select (channel);
	  has_space = 1;
	}
      else
	{
	  /* Otherwise, we can't send, because nobody is waiting to
	     receive.  */
	  has_space = 0;
	}

      if (has_space)
	{
	  channel->waiting_to_send = 1;
	  __go_assert (channel->next_store == 0);
	}
    }

  if (!has_space)
    {
      i = pthread_mutex_unlock (&channel->lock);
      __go_assert (i == 0);

      return 0;
    }

  return 1;
}
static void
sighandler (int sig)
{
  const char *msg;
  int i;

  if (sig == SIGPROF)
    {
      /* FIXME.  */
      runtime_sigprof (0, 0, nil);
      return;
    }

  /* FIXME: Should check siginfo for more information when
     available.  */
  msg = NULL;
  switch (sig)
    {
#ifdef SIGBUS
    case SIGBUS:
      msg = "invalid memory address or nil pointer dereference";
      break;
#endif

#ifdef SIGFPE
    case SIGFPE:
      msg = "integer divide by zero or floating point error";
      break;
#endif

#ifdef SIGSEGV
    case SIGSEGV:
      msg = "invalid memory address or nil pointer dereference";
      break;
#endif

    default:
      break;
    }

  if (msg != NULL)
    {
      sigset_t clear;

      if (__sync_bool_compare_and_swap (&m->mallocing, 1, 1))
	{
	  fprintf (stderr, "caught signal while mallocing: %s\n", msg);
	  __go_assert (0);
	}

      /* The signal handler blocked signals; unblock them.  */
      i = sigfillset (&clear);
      __go_assert (i == 0);
      i = sigprocmask (SIG_UNBLOCK, &clear, NULL);
      __go_assert (i == 0);

      __go_panic_msg (msg);
    }

  if (__go_sigsend (sig))
    return;
  for (i = 0; signals[i].sig != -1; ++i)
    {
      if (signals[i].sig == sig)
	{
	  struct sigaction sa;

	  if (signals[i].ignore)
	    return;

	  memset (&sa, 0, sizeof sa);

	  sa.sa_handler = SIG_DFL;

	  i = sigemptyset (&sa.sa_mask);
	  __go_assert (i == 0);

	  if (sigaction (sig, &sa, NULL) != 0)
	    abort ();

	  raise (sig);
	  exit (2);
	}
    }
  abort ();
}