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; }
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); } }
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; }
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); }
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 (); }