2011-10-08 Paul Thomas <pault@gcc.gnu.org>
[official-gcc.git] / libgo / runtime / go-new-channel.c
blob2f5bf2ea20ab6d67d554539b25f9abcf2e4a918a
1 /* go-new-channel.c -- allocate a new 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 <stddef.h>
8 #include <stdint.h>
10 #include "go-alloc.h"
11 #include "go-assert.h"
12 #include "go-panic.h"
13 #include "channel.h"
15 struct __go_channel*
16 __go_new_channel (const struct __go_type_descriptor *channel_type,
17 uintptr_t entries)
19 const struct __go_channel_type *ctd;
20 const struct __go_type_descriptor *element_type;
21 uintptr_t element_size;
22 int ientries;
23 struct __go_channel* ret;
24 size_t alloc_size;
25 int i;
27 __go_assert (channel_type->__code == GO_CHAN);
28 ctd = (const struct __go_channel_type *) channel_type;
29 element_type = ctd->__element_type;
31 element_size = element_type->__size;
33 ientries = (int) entries;
34 if (ientries < 0
35 || (uintptr_t) ientries != entries
36 || (element_size > 0 && entries > (uintptr_t) -1 / element_size))
37 __go_panic_msg ("chan size out of range");
39 alloc_size = (element_size + sizeof (uint64_t) - 1) / sizeof (uint64_t);
41 /* We use a circular buffer which means that when next_fetch ==
42 next_store we don't know whether the buffer is empty or full. So
43 we allocate an extra space, and always leave a space open.
44 FIXME. */
45 if (entries != 0)
46 ++entries;
48 ret = (struct __go_channel*) __go_alloc (sizeof (struct __go_channel)
49 + ((entries == 0 ? 1 : entries)
50 * alloc_size
51 * sizeof (uint64_t)));
52 i = pthread_mutex_init (&ret->lock, NULL);
53 __go_assert (i == 0);
54 i = pthread_cond_init (&ret->cond, NULL);
55 __go_assert (i == 0);
56 ret->element_type = element_type;
57 ret->waiting_to_send = 0;
58 ret->waiting_to_receive = 0;
59 ret->selected_for_send = 0;
60 ret->selected_for_receive = 0;
61 ret->is_closed = 0;
62 ret->select_send_queue = NULL;
63 ret->select_receive_queue = NULL;
64 ret->select_mutex = NULL;
65 ret->select_cond = NULL;
66 ret->num_entries = entries;
67 ret->next_store = 0;
68 ret->next_fetch = 0;
69 return ret;