PR debug/47106
[official-gcc.git] / libgo / runtime / go-send-nb-small.c
blobf23ae016433b15d1ebb95a9983895f551ab3f78d
1 /* go-send-nb-small.c -- nonblocking send of something small on a channel.
3 Copyright 2009 The Go Authors. All rights reserved.
4 Use of this source code is governed by a BSD-style
5 license that can be found in the LICENSE file. */
7 #include <stdint.h>
9 #include "go-assert.h"
10 #include "go-panic.h"
11 #include "channel.h"
13 /* Prepare to send something on a nonblocking channel. */
15 int
16 __go_send_nonblocking_acquire (struct __go_channel *channel)
18 int i;
19 _Bool has_space;
21 i = pthread_mutex_lock (&channel->lock);
22 __go_assert (i == 0);
24 while (channel->selected_for_send)
26 i = pthread_cond_wait (&channel->cond, &channel->lock);
27 __go_assert (i == 0);
30 if (channel->is_closed)
32 ++channel->closed_op_count;
33 if (channel->closed_op_count >= MAX_CLOSED_OPERATIONS)
35 i = pthread_mutex_unlock (&channel->lock);
36 __go_assert (i == 0);
37 __go_panic_msg ("too many operations on closed channel");
39 i = pthread_mutex_unlock (&channel->lock);
40 __go_assert (i == 0);
41 return SEND_NONBLOCKING_ACQUIRE_CLOSED;
44 if (channel->num_entries > 0)
45 has_space = ((channel->next_store + 1) % channel->num_entries
46 != channel->next_fetch);
47 else
49 /* This is a synchronous channel. If somebody is current
50 sending, then we can't send. Otherwise, see if somebody is
51 waiting to receive, or see if we can synch with a select. */
52 if (channel->waiting_to_send)
54 /* Some other goroutine is currently sending on this
55 channel, which means that we can't. */
56 has_space = 0;
58 else if (channel->waiting_to_receive)
60 /* Some other goroutine is waiting to receive a value, so we
61 can send directly to them. */
62 has_space = 1;
64 else if (__go_synch_with_select (channel, 1))
66 /* We found a select waiting to receive data, so we can send
67 to that. */
68 __go_broadcast_to_select (channel);
69 has_space = 1;
71 else
73 /* Otherwise, we can't send, because nobody is waiting to
74 receive. */
75 has_space = 0;
78 if (has_space)
80 channel->waiting_to_send = 1;
81 __go_assert (channel->next_store == 0);
85 if (!has_space)
87 i = pthread_mutex_unlock (&channel->lock);
88 __go_assert (i == 0);
90 return SEND_NONBLOCKING_ACQUIRE_NOSPACE;
93 return SEND_NONBLOCKING_ACQUIRE_SPACE;
96 /* Send something 64 bits or smaller on a channel. */
98 _Bool
99 __go_send_nonblocking_small (struct __go_channel *channel, uint64_t val)
101 __go_assert (channel->element_size <= sizeof (uint64_t));
103 int data = __go_send_nonblocking_acquire (channel);
104 if (data != SEND_NONBLOCKING_ACQUIRE_SPACE)
105 return data == SEND_NONBLOCKING_ACQUIRE_CLOSED;
107 channel->data[channel->next_store] = val;
109 __go_send_release (channel);
111 return 1;