OSDN Git Service

runtime: If O_CLOEXEC is not defined, define it as 0.
[pf3gnuchains/gcc-fork.git] / libgo / runtime / go-send-nb-small.c
1 /* go-send-nb-small.c -- nonblocking send of something small on a channel.
2
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.  */
6
7 #include <stdint.h>
8
9 #include "runtime.h"
10 #include "go-assert.h"
11 #include "go-panic.h"
12 #include "channel.h"
13
14 /* Prepare to send something on a nonblocking channel.  Return true if
15    we acquired the channel, false if we did not acquire it because
16    there is no space to send a value.  */
17
18 _Bool
19 __go_send_nonblocking_acquire (struct __go_channel *channel)
20 {
21   int i;
22   _Bool has_space;
23
24   i = pthread_mutex_lock (&channel->lock);
25   __go_assert (i == 0);
26
27   while (channel->selected_for_send)
28     runtime_cond_wait (&channel->cond, &channel->lock);
29
30   if (channel->is_closed)
31     {
32       i = pthread_mutex_unlock (&channel->lock);
33       __go_assert (i == 0);
34       __go_panic_msg ("send on closed channel");
35     }
36
37   if (channel->num_entries > 0)
38       has_space = ((channel->next_store + 1) % channel->num_entries
39                    != channel->next_fetch);
40   else
41     {
42       /* This is a synchronous channel.  If somebody is current
43          sending, then we can't send.  Otherwise, see if somebody is
44          waiting to receive, or see if we can synch with a select.  */
45       if (channel->waiting_to_send)
46         {
47           /* Some other goroutine is currently sending on this
48              channel, which means that we can't.  */
49           has_space = 0;
50         }
51       else if (channel->waiting_to_receive)
52         {
53           /* Some other goroutine is waiting to receive a value, so we
54              can send directly to them.  */
55           has_space = 1;
56         }
57       else if (__go_synch_with_select (channel, 1))
58         {
59           /* We found a select waiting to receive data, so we can send
60              to that.  */
61           __go_broadcast_to_select (channel);
62           has_space = 1;
63         }
64       else
65         {
66           /* Otherwise, we can't send, because nobody is waiting to
67              receive.  */
68           has_space = 0;
69         }
70
71       if (has_space)
72         {
73           channel->waiting_to_send = 1;
74           __go_assert (channel->next_store == 0);
75         }
76     }
77
78   if (!has_space)
79     {
80       i = pthread_mutex_unlock (&channel->lock);
81       __go_assert (i == 0);
82
83       return 0;
84     }
85
86   return 1;
87 }
88
89 /* Send something 64 bits or smaller on a channel.  */
90
91 _Bool
92 __go_send_nonblocking_small (struct __go_channel *channel, uint64_t val)
93 {
94   if (channel == NULL)
95     return 0;
96
97   __go_assert (channel->element_type->__size <= sizeof (uint64_t));
98
99   if (!__go_send_nonblocking_acquire (channel))
100     return 0;
101
102   channel->data[channel->next_store] = val;
103
104   __go_send_release (channel);
105
106   return 1;
107 }