Пример #1
0
void
setenv_c (String k, String v)
{
  const byte *ks;
  unsigned char *kn;
  const byte *vs;
  unsigned char *vn;

  ks = k.str;
  if (ks == NULL)
    ks = (const byte *) "";
  kn = NULL;

  vs = v.str;
  if (vs == NULL)
    vs = (const byte *) "";
  vn = NULL;

#ifdef HAVE_SETENV

  if (ks != NULL && ks[k.len] != 0)
    {
      kn = __go_alloc (k.len + 1);
      __builtin_memcpy (kn, ks, k.len);
      ks = kn;
    }

  if (vs != NULL && vs[v.len] != 0)
    {
      vn = __go_alloc (v.len + 1);
      __builtin_memcpy (vn, vs, v.len);
      vs = vn;
    }

  setenv ((const char *) ks, (const char *) vs, 1);

#else /* !defined(HAVE_SETENV) */

  kn = __go_alloc (k.len + v.len + 2);
  __builtin_memcpy (kn, ks, k.len);
  kn[k.len] = '=';
  __builtin_memcpy (kn + k.len + 1, vs, v.len);
  kn[k.len + v.len + 1] = '\0';
  putenv ((char *) kn);

#endif /* !defined(HAVE_SETENV) */

  if (kn != NULL)
    __go_free (kn);
  if (vn != NULL)
    __go_free (vn);
}
Пример #2
0
void
unsetenv_c (String k)
{
  const byte *ks;
  unsigned char *kn;

  ks = k.str;
  if (ks == NULL)
    ks = (const byte *) "";
  kn = NULL;

#ifdef HAVE_UNSETENV
  intgo len;

  if (ks != NULL && ks[k.len] != 0)
    {
      // Objects that are explicitly freed must be at least 16 bytes in size,
      // so that they are not allocated using tiny alloc.
      len = k.len + 1;
      if (len < TinySize)
	len = TinySize;
      kn = __go_alloc (len);
      __builtin_memcpy (kn, ks, k.len);
      ks = kn;
    }

  unsetenv ((const char *) ks);

#endif /* !defined(HAVE_UNSETENV) */

  if (kn != NULL)
    __go_free (kn);
}
Пример #3
0
void
__go_undefer (_Bool *frame)
{
  G *g;

  g = runtime_g ();
  while (g->defer != NULL && g->defer->__frame == frame)
    {
      struct __go_defer_stack *d;
      void (*pfn) (void *);

      d = g->defer;
      pfn = d->__pfn;
      d->__pfn = NULL;

      if (pfn != NULL)
	(*pfn) (d->__arg);

      g->defer = d->__next;
      __go_free (d);

      /* Since we are executing a defer function here, we know we are
	 returning from the calling function.  If the calling
	 function, or one of its callees, paniced, then the defer
	 functions would be executed by __go_panic.  */
      *frame = 1;
    }
}
Пример #4
0
static void
__go_map_rehash (struct __go_map *map)
{
  const struct __go_map_descriptor *descriptor;
  const struct __go_type_descriptor *key_descriptor;
  uintptr_t key_offset;
  size_t key_size;
  size_t (*hashfn) (const void *, size_t);
  uintptr_t old_bucket_count;
  void **old_buckets;
  uintptr_t new_bucket_count;
  void **new_buckets;
  uintptr_t i;

  descriptor = map->__descriptor;

  key_descriptor = descriptor->__map_descriptor->__key_type;
  key_offset = descriptor->__key_offset;
  key_size = key_descriptor->__size;
  hashfn = key_descriptor->__hashfn;

  old_bucket_count = map->__bucket_count;
  old_buckets = map->__buckets;

  new_bucket_count = __go_map_next_prime (old_bucket_count * 2);
  new_buckets = (void **) __go_alloc (new_bucket_count * sizeof (void *));
  __builtin_memset (new_buckets, 0, new_bucket_count * sizeof (void *));

  for (i = 0; i < old_bucket_count; ++i)
    {
      char* entry;
      char* next;

      for (entry = old_buckets[i]; entry != NULL; entry = next)
	{
	  size_t key_hash;
	  size_t new_bucket_index;

	  /* We could speed up rehashing at the cost of memory space
	     by caching the hash code.  */
	  key_hash = hashfn (entry + key_offset, key_size);
	  new_bucket_index = key_hash % new_bucket_count;

	  next = *(char **) entry;
	  *(char **) entry = new_buckets[new_bucket_index];
	  new_buckets[new_bucket_index] = entry;
	}
    }

  __go_free (old_buckets);

  map->__bucket_count = new_bucket_count;
  map->__buckets = new_buckets;
}
Пример #5
0
void
__go_map_delete (struct __go_map *map, const void *key)
{
  const struct __go_map_descriptor *descriptor;
  const struct __go_type_descriptor *key_descriptor;
  uintptr_t key_offset;
  _Bool (*equalfn) (const void*, const void*, uintptr_t);
  size_t key_hash;
  size_t key_size;
  size_t bucket_index;
  void **pentry;

  if (map == NULL)
    runtime_panicstring ("deletion of entry in nil map");

  descriptor = map->__descriptor;

  key_descriptor = descriptor->__map_descriptor->__key_type;
  key_offset = descriptor->__key_offset;
  key_size = key_descriptor->__size;
  __go_assert (key_size != 0 && key_size != -1UL);
  equalfn = key_descriptor->__equalfn;

  key_hash = key_descriptor->__hashfn (key, key_size);
  bucket_index = key_hash % map->__bucket_count;

  pentry = map->__buckets + bucket_index;
  while (*pentry != NULL)
    {
      char *entry = (char *) *pentry;
      if (equalfn (key, entry + key_offset, key_size))
	{
	  *pentry = *(void **) entry;
	  __go_free (entry);
	  map->__element_count -= 1;
	  break;
	}
      pentry = (void **) entry;
    }
}
Пример #6
0
void
__go_undefer (_Bool *frame)
{
  G *g;

  g = runtime_g ();
  while (g->defer != NULL && g->defer->__frame == frame)
    {
      struct __go_defer_stack *d;
      void (*pfn) (void *);
      M *m;

      d = g->defer;
      pfn = d->__pfn;
      d->__pfn = NULL;

      if (pfn != NULL)
	(*pfn) (d->__arg);

      g->defer = d->__next;

      /* This may be called by a cgo callback routine to defer the
	 call to syscall.CgocallBackDone, in which case we will not
	 have a memory context.  Don't try to free anything in that
	 case--the GC will release it later.  */
      m = runtime_m ();
      if (m != NULL && m->mcache != NULL && d->__free)
	__go_free (d);

      /* Since we are executing a defer function here, we know we are
	 returning from the calling function.  If the calling
	 function, or one of its callees, paniced, then the defer
	 functions would be executed by __go_panic.  */
      *frame = 1;
    }
}
Пример #7
0
void
__go_panic (struct __go_empty_interface arg)
{
  G *g;
  Panic *n;

  g = runtime_g ();

  n = (Panic *) __go_alloc (sizeof (Panic));
  n->arg = arg;
  n->next = g->_panic;
  g->_panic = n;

  /* Run all the defer functions.  */

  while (1)
    {
      Defer *d;
      void (*pfn) (void *);

      d = g->_defer;
      if (d == NULL)
	break;

      pfn = (void (*) (void *)) d->pfn;
      d->pfn = 0;

      if (pfn != NULL)
	{
	  (*pfn) (d->arg);

	  if (n->recovered)
	    {
	      /* Some defer function called recover.  That means that
		 we should stop running this panic.  */

	      g->_panic = n->next;
	      __go_free (n);

	      /* Now unwind the stack by throwing an exception.  The
		 compiler has arranged to create exception handlers in
		 each function which uses a defer statement.  These
		 exception handlers will check whether the entry on
		 the top of the defer stack is from the current
		 function.  If it is, we have unwound the stack far
		 enough.  */
	      __go_unwind_stack ();

	      /* __go_unwind_stack should not return.  */
	      abort ();
	    }

	  /* Because we executed that defer function by a panic, and
	     it did not call recover, we know that we are not
	     returning from the calling function--we are panicing
	     through it.  */
	  *d->frame = 0;
	}

      g->_defer = d->next;

      /* This may be called by a cgo callback routine to defer the
	 call to syscall.CgocallBackDone, in which case we will not
	 have a memory context.  Don't try to free anything in that
	 case--the GC will release it later.  */
      if (runtime_m () != NULL)
	runtime_freedefer (d);
    }

  /* The panic was not recovered.  */

  runtime_startpanic ();
  __printpanics (g->_panic);
  runtime_dopanic (0);
}
Пример #8
0
void
__go_check_defer (_Bool *frame)
{
  G *g;
  struct _Unwind_Exception *hdr;

  g = runtime_g ();

  if (g == NULL)
    {
      /* Some other language has thrown an exception.  We know there
	 are no defer handlers, so there is nothing to do.  */
    }
  else if (g->isforeign)
    {
      Panic *n;
      _Bool recovered;

      /* Some other language has thrown an exception.  We need to run
	 the local defer handlers.  If they call recover, we stop
	 unwinding the stack here.  */

      n = (Panic *) __go_alloc (sizeof (Panic));

      n->arg.__type_descriptor = NULL;
      n->arg.__object = NULL;
      n->recovered = 0;
      n->isforeign = 1;
      n->next = g->_panic;
      g->_panic = n;

      while (1)
	{
	  Defer *d;
	  void (*pfn) (void *);

	  d = g->_defer;
	  if (d == NULL || d->frame != frame || d->pfn == 0)
	    break;

	  pfn = (void (*) (void *)) d->pfn;
	  g->_defer = d->next;

	  (*pfn) (d->arg);

	  if (runtime_m () != NULL)
	    runtime_freedefer (d);

	  if (n->recovered)
	    {
	      /* The recover function caught the panic thrown by some
		 other language.  */
	      break;
	    }
	}

      recovered = n->recovered;
      g->_panic = n->next;
      __go_free (n);

      if (recovered)
	{
	  /* Just return and continue executing Go code.  */
	  *frame = 1;
	  return;
	}

      /* We are panicing through this function.  */
      *frame = 0;
    }
  else if (g->_defer != NULL
	   && g->_defer->pfn == 0
	   && g->_defer->frame == frame)
    {
      Defer *d;

      /* This is the defer function which called recover.  Simply
	 return to stop the stack unwind, and let the Go code continue
	 to execute.  */
      d = g->_defer;
      g->_defer = d->next;

      if (runtime_m () != NULL)
	runtime_freedefer (d);

      /* We are returning from this function.  */
      *frame = 1;

      return;
    }

  /* This is some other defer function.  It was already run by the
     call to panic, or just above.  Rethrow the exception.  */

  hdr = (struct _Unwind_Exception *) g->exception;

#ifdef __USING_SJLJ_EXCEPTIONS__
  _Unwind_SjLj_Resume_or_Rethrow (hdr);
#else
#if defined(_LIBUNWIND_STD_ABI)
  _Unwind_RaiseException (hdr);
#else
  _Unwind_Resume_or_Rethrow (hdr);
#endif
#endif

  /* Rethrowing the exception should not return.  */
  abort();
}
Пример #9
0
void
__go_panic (struct __go_empty_interface arg)
{
  struct __go_panic_stack *n;

  if (__go_panic_defer == NULL)
    __go_panic_defer = ((struct __go_panic_defer_struct *)
			__go_alloc (sizeof (struct __go_panic_defer_struct)));

  n = (struct __go_panic_stack *) __go_alloc (sizeof (struct __go_panic_stack));
  n->__arg = arg;
  n->__next = __go_panic_defer->__panic;
  __go_panic_defer->__panic = n;

  /* Run all the defer functions.  */

  while (1)
    {
      struct __go_defer_stack *d;
      void (*pfn) (void *);

      d = __go_panic_defer->__defer;
      if (d == NULL)
	break;

      pfn = d->__pfn;
      d->__pfn = NULL;

      if (pfn != NULL)
	{
	  (*pfn) (d->__arg);

	  if (n->__was_recovered)
	    {
	      /* Some defer function called recover.  That means that
		 we should stop running this panic.  */

	      __go_panic_defer->__panic = n->__next;
	      __go_free (n);

	      /* Now unwind the stack by throwing an exception.  The
		 compiler has arranged to create exception handlers in
		 each function which uses a defer statement.  These
		 exception handlers will check whether the entry on
		 the top of the defer stack is from the current
		 function.  If it is, we have unwound the stack far
		 enough.  */
	      __go_unwind_stack ();

	      /* __go_unwind_stack should not return.  */
	      abort ();
	    }
	}

      __go_panic_defer->__defer = d->__next;
      __go_free (d);
    }

  /* The panic was not recovered.  */

  __printpanics (__go_panic_defer->__panic);

  /* FIXME: We should dump a call stack here.  */
  abort ();
}