aboutsummaryrefslogtreecommitdiff
path: root/libgo
diff options
context:
space:
mode:
authorIan Lance Taylor <ian@gcc.gnu.org>2011-03-23 21:13:57 +0000
committerIan Lance Taylor <ian@gcc.gnu.org>2011-03-23 21:13:57 +0000
commit4bfc521c9eeadaac02870c419fad9ba67da0ff3c (patch)
tree4d857e22ad7943fcdeeebd79414e85dc2eb195ba /libgo
parent4573f2cb64ad73945718526e29ead98eaf93de03 (diff)
downloadgcc-4bfc521c9eeadaac02870c419fad9ba67da0ff3c.zip
gcc-4bfc521c9eeadaac02870c419fad9ba67da0ff3c.tar.gz
gcc-4bfc521c9eeadaac02870c419fad9ba67da0ff3c.tar.bz2
Send on a closed channel panics.
Calling close on a closed channel panics. Don't limit number of receives on a closed channel. From-SVN: r171364
Diffstat (limited to 'libgo')
-rw-r--r--libgo/runtime/channel.h13
-rw-r--r--libgo/runtime/go-close.c8
-rw-r--r--libgo/runtime/go-new-channel.c1
-rw-r--r--libgo/runtime/go-rec-nb-small.c10
-rw-r--r--libgo/runtime/go-rec-small.c6
-rw-r--r--libgo/runtime/go-send-big.c3
-rw-r--r--libgo/runtime/go-send-nb-big.c5
-rw-r--r--libgo/runtime/go-send-nb-small.c24
-rw-r--r--libgo/runtime/go-send-small.c28
9 files changed, 32 insertions, 66 deletions
diff --git a/libgo/runtime/channel.h b/libgo/runtime/channel.h
index b0d1347..5d2f49f 100644
--- a/libgo/runtime/channel.h
+++ b/libgo/runtime/channel.h
@@ -36,8 +36,6 @@ struct __go_channel
pthread_cond_t cond;
/* The size of elements on this channel. */
size_t element_size;
- /* Number of operations on closed channel. */
- unsigned short closed_op_count;
/* True if a goroutine is waiting to send on a synchronous
channel. */
_Bool waiting_to_send;
@@ -84,22 +82,15 @@ struct __go_channel
acquired while this mutex is held. */
extern pthread_mutex_t __go_select_data_mutex;
-/* Maximum permitted number of operations on a closed channel. */
-#define MAX_CLOSED_OPERATIONS (0x100)
-
extern struct __go_channel *__go_new_channel (size_t, size_t);
extern _Bool __go_synch_with_select (struct __go_channel *, _Bool);
extern void __go_broadcast_to_select (struct __go_channel *);
-extern _Bool __go_send_acquire (struct __go_channel *, _Bool);
-
-#define SEND_NONBLOCKING_ACQUIRE_SPACE 0
-#define SEND_NONBLOCKING_ACQUIRE_NOSPACE 1
-#define SEND_NONBLOCKING_ACQUIRE_CLOSED 2
+extern void __go_send_acquire (struct __go_channel *, _Bool);
-extern int __go_send_nonblocking_acquire (struct __go_channel *);
+extern _Bool __go_send_nonblocking_acquire (struct __go_channel *);
extern void __go_send_release (struct __go_channel *);
diff --git a/libgo/runtime/go-close.c b/libgo/runtime/go-close.c
index ced7429..44533eb 100644
--- a/libgo/runtime/go-close.c
+++ b/libgo/runtime/go-close.c
@@ -5,6 +5,7 @@
license that can be found in the LICENSE file. */
#include "go-assert.h"
+#include "go-panic.h"
#include "channel.h"
/* Close a channel. After a channel is closed, sends are no longer
@@ -24,6 +25,13 @@ __go_builtin_close (struct __go_channel *channel)
__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);
diff --git a/libgo/runtime/go-new-channel.c b/libgo/runtime/go-new-channel.c
index d57f52c..d16bde6 100644
--- a/libgo/runtime/go-new-channel.c
+++ b/libgo/runtime/go-new-channel.c
@@ -39,7 +39,6 @@ __go_new_channel (size_t element_size, size_t entries)
i = pthread_cond_init (&ret->cond, NULL);
__go_assert (i == 0);
ret->element_size = element_size;
- ret->closed_op_count = 0;
ret->waiting_to_send = 0;
ret->waiting_to_receive = 0;
ret->selected_for_send = 0;
diff --git a/libgo/runtime/go-rec-nb-small.c b/libgo/runtime/go-rec-nb-small.c
index 9983d34..d77a2ac 100644
--- a/libgo/runtime/go-rec-nb-small.c
+++ b/libgo/runtime/go-rec-nb-small.c
@@ -32,16 +32,6 @@ __go_receive_nonblocking_acquire (struct __go_channel *channel)
? channel->next_store == 0
: channel->next_fetch == channel->next_store))
{
- if (channel->saw_close)
- {
- ++channel->closed_op_count;
- if (channel->closed_op_count >= MAX_CLOSED_OPERATIONS)
- {
- i = pthread_mutex_unlock (&channel->lock);
- __go_assert (i == 0);
- __go_panic_msg ("too many operations on closed channel");
- }
- }
channel->saw_close = 1;
__go_unlock_and_notify_selects (channel);
return RECEIVE_NONBLOCKING_ACQUIRE_CLOSED;
diff --git a/libgo/runtime/go-rec-small.c b/libgo/runtime/go-rec-small.c
index 765e8d3..c4dc8b6 100644
--- a/libgo/runtime/go-rec-small.c
+++ b/libgo/runtime/go-rec-small.c
@@ -123,12 +123,6 @@ __go_receive_acquire (struct __go_channel *channel, _Bool for_select)
? channel->next_store == 0
: channel->next_fetch == channel->next_store))
{
- if (channel->saw_close)
- {
- ++channel->closed_op_count;
- if (channel->closed_op_count >= MAX_CLOSED_OPERATIONS)
- __go_panic_msg ("too many operations on closed channel");
- }
channel->saw_close = 1;
channel->selected_for_receive = 0;
__go_unlock_and_notify_selects (channel);
diff --git a/libgo/runtime/go-send-big.c b/libgo/runtime/go-send-big.c
index f58ffb6..c273263 100644
--- a/libgo/runtime/go-send-big.c
+++ b/libgo/runtime/go-send-big.c
@@ -21,8 +21,7 @@ __go_send_big (struct __go_channel* channel, const void *val, _Bool for_select)
alloc_size = ((channel->element_size + sizeof (uint64_t) - 1)
/ sizeof (uint64_t));
- if (!__go_send_acquire (channel, for_select))
- return;
+ __go_send_acquire (channel, for_select);
offset = channel->next_store * alloc_size;
__builtin_memcpy (&channel->data[offset], val, channel->element_size);
diff --git a/libgo/runtime/go-send-nb-big.c b/libgo/runtime/go-send-nb-big.c
index 288ce7f..1d33dd6 100644
--- a/libgo/runtime/go-send-nb-big.c
+++ b/libgo/runtime/go-send-nb-big.c
@@ -17,9 +17,8 @@ __go_send_nonblocking_big (struct __go_channel* channel, const void *val)
alloc_size = ((channel->element_size + sizeof (uint64_t) - 1)
/ sizeof (uint64_t));
- int data = __go_send_nonblocking_acquire (channel);
- if (data != SEND_NONBLOCKING_ACQUIRE_SPACE)
- return data == SEND_NONBLOCKING_ACQUIRE_CLOSED;
+ if (!__go_send_nonblocking_acquire (channel))
+ return 0;
offset = channel->next_store * alloc_size;
__builtin_memcpy (&channel->data[offset], val, channel->element_size);
diff --git a/libgo/runtime/go-send-nb-small.c b/libgo/runtime/go-send-nb-small.c
index f23ae01..5c49a67 100644
--- a/libgo/runtime/go-send-nb-small.c
+++ b/libgo/runtime/go-send-nb-small.c
@@ -10,9 +10,11 @@
#include "go-panic.h"
#include "channel.h"
-/* Prepare to send something on a nonblocking channel. */
+/* Prepare to send something on a nonblocking channel. Return true if
+ we acquired the channel, false if we did not acquire it because
+ there is no space to send a value. */
-int
+_Bool
__go_send_nonblocking_acquire (struct __go_channel *channel)
{
int i;
@@ -29,16 +31,9 @@ __go_send_nonblocking_acquire (struct __go_channel *channel)
if (channel->is_closed)
{
- ++channel->closed_op_count;
- if (channel->closed_op_count >= MAX_CLOSED_OPERATIONS)
- {
- i = pthread_mutex_unlock (&channel->lock);
- __go_assert (i == 0);
- __go_panic_msg ("too many operations on closed channel");
- }
i = pthread_mutex_unlock (&channel->lock);
__go_assert (i == 0);
- return SEND_NONBLOCKING_ACQUIRE_CLOSED;
+ __go_panic_msg ("send on closed channel");
}
if (channel->num_entries > 0)
@@ -87,10 +82,10 @@ __go_send_nonblocking_acquire (struct __go_channel *channel)
i = pthread_mutex_unlock (&channel->lock);
__go_assert (i == 0);
- return SEND_NONBLOCKING_ACQUIRE_NOSPACE;
+ return 0;
}
- return SEND_NONBLOCKING_ACQUIRE_SPACE;
+ return 1;
}
/* Send something 64 bits or smaller on a channel. */
@@ -100,9 +95,8 @@ __go_send_nonblocking_small (struct __go_channel *channel, uint64_t val)
{
__go_assert (channel->element_size <= sizeof (uint64_t));
- int data = __go_send_nonblocking_acquire (channel);
- if (data != SEND_NONBLOCKING_ACQUIRE_SPACE)
- return data == SEND_NONBLOCKING_ACQUIRE_CLOSED;
+ if (!__go_send_nonblocking_acquire (channel))
+ return 0;
channel->data[channel->next_store] = val;
diff --git a/libgo/runtime/go-send-small.c b/libgo/runtime/go-send-small.c
index 506c90e..56f9470 100644
--- a/libgo/runtime/go-send-small.c
+++ b/libgo/runtime/go-send-small.c
@@ -10,12 +10,11 @@
#include "go-panic.h"
#include "channel.h"
-/* Prepare to send something on a channel. Return true if the channel
- is acquired, false, if it is closed. FOR_SELECT is true if this
+/* Prepare to send something on a channel. FOR_SELECT is true if this
call is being made after a select statement returned with this
channel selected. */
-_Bool
+void
__go_send_acquire (struct __go_channel *channel, _Bool for_select)
{
int i;
@@ -25,19 +24,13 @@ __go_send_acquire (struct __go_channel *channel, _Bool for_select)
while (1)
{
- /* Check whether the channel is closed. */
if (channel->is_closed)
{
- ++channel->closed_op_count;
- if (channel->closed_op_count >= MAX_CLOSED_OPERATIONS)
- {
- i = pthread_mutex_unlock (&channel->lock);
- __go_assert (i == 0);
- __go_panic_msg ("too many operations on closed channel");
- }
- channel->selected_for_send = 0;
- __go_unlock_and_notify_selects (channel);
- return 0;
+ 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
@@ -54,7 +47,7 @@ __go_send_acquire (struct __go_channel *channel, _Bool for_select)
if (!channel->waiting_to_send)
{
__go_assert (channel->next_store == 0);
- return 1;
+ return;
}
}
else
@@ -62,7 +55,7 @@ __go_send_acquire (struct __go_channel *channel, _Bool for_select)
/* If there is room on the channel, we are OK. */
if ((channel->next_store + 1) % channel->num_entries
!= channel->next_fetch)
- return 1;
+ return;
}
}
@@ -156,8 +149,7 @@ __go_send_small (struct __go_channel *channel, uint64_t val, _Bool for_select)
__go_assert (channel->element_size <= sizeof (uint64_t));
- if (!__go_send_acquire (channel, for_select))
- return;
+ __go_send_acquire (channel, for_select);
channel->data[channel->next_store] = val;