The ROme OpTimistic Simulator  2.0.0
A General-Purpose Multithreaded Parallel/Distributed Simulation Platform
msgchannel.c
Go to the documentation of this file.
1 
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <string.h>
33 
34 #include <arch/atomic.h>
35 #include <core/core.h>
37 #include <datatypes/list.h>
38 #include <datatypes/msgchannel.h>
39 #include <mm/mm.h>
40 
41 // These are used to simplify reading the code
42 #define M_WRITE 0
43 #define M_READ 1
44 
45 static void switch_channel_buffers(msg_channel * mc)
46 {
47  struct _msg_buff *volatile swap;
48 
49  mc->buffers[M_WRITE]->read = 0;
50  mc->buffers[M_READ]->written = 0;
51 
52  swap = mc->buffers[M_WRITE];
53  mc->buffers[M_WRITE] = mc->buffers[M_READ];
54  mc->buffers[M_READ] = swap;
55 }
56 
57 void fini_channel(msg_channel * mc)
58 {
59  rsfree((void *)mc->buffers[M_WRITE]->buffer);
60  rsfree((void *)mc->buffers[M_READ]->buffer);
61  rsfree(mc->buffers[M_WRITE]);
62  rsfree(mc->buffers[M_READ]);
63  rsfree(mc);
64 }
65 
66 msg_channel *init_channel(void)
67 {
68  msg_channel *mc = rsalloc(sizeof(msg_channel));
69 
70  mc->buffers[M_READ] = rsalloc(sizeof(struct _msg_buff));
71  mc->buffers[M_WRITE] = rsalloc(sizeof(struct _msg_buff));
72 
73  if (mc->buffers[M_READ] == NULL || mc->buffers[M_WRITE] == NULL)
74  rootsim_error(true, "Unable to allocate message channel\n");
75 
76  mc->buffers[M_READ]->buffer =
77  rsalloc(INITIAL_CHANNEL_SIZE * sizeof(msg_t *));
78  mc->buffers[M_READ]->size = INITIAL_CHANNEL_SIZE;
79  mc->buffers[M_READ]->written = 0;
80  mc->buffers[M_READ]->read = 0;
81 
82  mc->buffers[M_WRITE]->buffer =
83  rsalloc(INITIAL_CHANNEL_SIZE * sizeof(msg_t *));
84  mc->buffers[M_WRITE]->size = INITIAL_CHANNEL_SIZE;
85  mc->buffers[M_WRITE]->written = 0;
86  mc->buffers[M_WRITE]->read = 0;
87 
88  if (mc->buffers[M_READ]->buffer == NULL
89  || mc->buffers[M_WRITE]->buffer == NULL)
90  rootsim_error(true, "Unable to allocate message channel\n");
91 
92  spinlock_init(&mc->write_lock);
93 
94  return mc;
95 }
96 
97 void insert_msg(msg_channel * mc, msg_t * msg)
98 {
99 
100  spin_lock(&mc->write_lock);
101 
102  // Reallocate the live BH buffer. Don't touch the other buffer,
103  // as in this way the critical section is much shorter
104  if (unlikely
105  (mc->buffers[M_WRITE]->written == mc->buffers[M_WRITE]->size)) {
106 
107  mc->buffers[M_WRITE]->size *= 2;
108  mc->buffers[M_WRITE]->buffer =
109  rsrealloc((void *)mc->buffers[M_WRITE]->buffer,
110  mc->buffers[M_WRITE]->size * sizeof(msg_t *));
111 
112  if (unlikely(mc->buffers[M_WRITE]->buffer == NULL))
113  rootsim_error(true, "Unable to reallocate message channel\n");
114 
115  }
116 #ifndef NDEBUG
117  validate_msg(msg);
118 #endif
119 
120  int index = mc->buffers[M_WRITE]->written++;
121  mc->buffers[M_WRITE]->buffer[index] = msg;
122 
123  spin_unlock(&mc->write_lock);
124 }
125 
126 void *get_msg(msg_channel * mc)
127 {
128  msg_t *msg = NULL;
129 
130  if (unlikely(mc->buffers[M_READ]->read == mc->buffers[M_READ]->written)) {
131  spin_lock(&mc->write_lock);
132  switch_channel_buffers(mc);
133  spin_unlock(&mc->write_lock);
134  }
135 
136  if (unlikely(mc->buffers[M_READ]->read == mc->buffers[M_READ]->written)) {
137  goto leave;
138  }
139 
140  int index = mc->buffers[M_READ]->read++;
141  msg = mc->buffers[M_READ]->buffer[index];
142  atomic_dec(&mc->size);
143 
144 #ifndef NDEBUG
145  mc->buffers[M_READ]->buffer[index] = (void *)0xDEADB00B;
146  validate_msg(msg);
147 #endif
148 
149  leave:
150  return msg;
151 }
Communication Routines.
#define spinlock_init(s)
Spinlock initialization.
Definition: atomic.h:72
A (M, 1) channel for messages.
Core ROOT-Sim functionalities.
void atomic_dec(atomic_t *)
Definition: x86.c:103
Memory Manager main header.
Generic Lists.
Message Type definition.
Definition: core.h:164
void spin_lock(spinlock_t *s)
Definition: x86.c:135
Atomic operations.
void validate_msg(msg_t *msg)
Perform some sanity checks on a message buffer.
#define unlikely(exp)
Optimize the branch as likely not taken.
Definition: core.h:74
void spin_unlock(spinlock_t *s)
Definition: x86.c:161