ns-3 Direct Code Execution
API
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
dce-semaphore.cc
Go to the documentation of this file.
1 #include "dce-semaphore.h"
2 #include "process.h"
3 #include "dce-manager.h"
4 #include "utils.h"
5 #include <stdint.h>
6 #include <errno.h>
7 #include "ns3/log.h"
8 #include "ns3/assert.h"
9 #include "ns3/fatal-error.h"
10 #include "ns3/simulator.h"
11 
12 NS_LOG_COMPONENT_DEFINE ("Semaphore");
13 
14 using namespace ns3;
15 
16 
17 static uint32_t AllocateSid (struct Process *process)
18 {
19  // check that semaphore structure is big enough to store our semaphore id
20  NS_ASSERT (sizeof (sem_t) > sizeof(uint16_t));
21  uint32_t sid = process->nextSid;
22  process->nextSid++;
23  return sid;
24 }
25 static void SidToSem (uint32_t sid, sem_t *sem)
26 {
27  uint32_t *psid = (uint32_t *)sem;
28  *psid = sid;
29 }
30 static uint32_t SemToSid (const sem_t *sem)
31 {
32  if (sem == 0)
33  {
34  return 0;
35  }
36  const uint32_t *psid = (const uint32_t *)sem;
37  return *psid;
38 }
39 static struct Semaphore *
40 SearchSemaphore (const sem_t *sem)
41 {
42  Thread *current = Current ();
43  if (sem == 0)
44  {
45  return 0;
46  }
47  uint32_t sid = SemToSid (sem);
48  for (uint32_t i = 0; i < current->process->semaphores.size (); ++i)
49  {
50  struct Semaphore *semaphore = current->process->semaphores[i];
51  if (semaphore->sid == sid)
52  {
53  return semaphore;
54  }
55  }
56  return 0;
57 }
58 
59 int dce_sem_init (sem_t *sem, int pshared, unsigned int value)
60 {
61  Thread *current = Current ();
62  NS_LOG_FUNCTION (current << sem << pshared << value);
63  NS_ASSERT (current != 0);
64 
65  if (pshared != 0)
66  {
67  current->err = ENOSYS;
68  return -1;
69  }
70  Semaphore *semaphore = new Semaphore ();
71  semaphore->sid = AllocateSid (current->process);
72  semaphore->count = value;
73  semaphore->waiting.clear ();
74  current->process->semaphores.push_back (semaphore);
75  SidToSem (semaphore->sid, sem);
76  return 0;
77 }
78 int dce_sem_destroy (sem_t *sem)
79 {
80  Thread *current = Current ();
81  NS_LOG_FUNCTION (current << UtilsGetNodeId () << sem);
82  NS_ASSERT (current != 0);
83  struct Semaphore *semaphore = SearchSemaphore (sem);
84  if (semaphore == 0)
85  {
86  current->err = EINVAL;
87  return -1;
88  }
89  if (!semaphore->waiting.empty ())
90  {
91  NS_FATAL_ERROR ("Trying to destroy a semaphore on which someone else is waiting.");
92  }
93  for (std::vector<struct Semaphore *>::iterator i = current->process->semaphores.begin ();
94  i != current->process->semaphores.end (); ++i)
95  {
96  if (semaphore == *i)
97  {
98  delete semaphore;
99  semaphore = 0;
100  current->process->semaphores.erase (i);
101  break;
102  }
103  }
104  NS_ASSERT (semaphore == 0);
105  SidToSem (2, sem);
106  return 0;
107 }
108 int dce_sem_post (sem_t *sem)
109 {
110  Thread *current = Current ();
111  NS_LOG_FUNCTION (current << UtilsGetNodeId () << sem);
112  NS_ASSERT (current != 0);
113 
114  struct Semaphore *semaphore = SearchSemaphore (sem);
115  if (semaphore == 0)
116  {
117  current->err = EINVAL;
118  return -1;
119  }
120 
121  semaphore->count++;
122 
123  if (!semaphore->waiting.empty ())
124  {
125  // FIFO order for threads blocked on the semaphore waiting for it.
126  Thread *waiting = semaphore->waiting.front ();
127  current->process->manager->Wakeup (waiting);
128  // give them a chance to run.
129  current->process->manager->Yield ();
130  }
131 
132  return 0;
133 }
134 int dce_sem_wait (sem_t *sem)
135 {
136  Thread *current = Current ();
137  NS_LOG_FUNCTION (current << UtilsGetNodeId () << sem);
138  NS_ASSERT (current != 0);
139 
140  struct Semaphore *semaphore = SearchSemaphore (sem);
141  if (semaphore == 0)
142  {
143  current->err = EINVAL;
144  return -1;
145  }
146  while (semaphore->count == 0)
147  {
148  semaphore->waiting.push_back (current);
149  current->process->manager->Wait ();
150  semaphore->waiting.remove (current);
151  }
152  semaphore->count--;
153  return 0;
154 }
155 int dce_sem_trywait (sem_t *sem)
156 {
157  Thread *current = Current ();
158  NS_LOG_FUNCTION (current << UtilsGetNodeId () << sem);
159  NS_ASSERT (current != 0);
160 
161  struct Semaphore *semaphore = SearchSemaphore (sem);
162  if (semaphore == 0)
163  {
164  current->err = EINVAL;
165  return -1;
166  }
167  if (semaphore->count == 0)
168  {
169  current->err = EAGAIN;
170  return -1;
171  }
172  semaphore->count--;
173  return 0;
174 }
175 int dce_sem_timedwait (sem_t *sem, const struct timespec *abs_timeout)
176 {
177  Thread *current = Current ();
178  NS_LOG_FUNCTION (current << UtilsGetNodeId () << sem);
179  NS_ASSERT (current != 0);
180 
181  struct Semaphore *semaphore = SearchSemaphore (sem);
182  if (semaphore == 0)
183  {
184  current->err = EINVAL;
185  return -1;
186  }
187 
188  if (semaphore->count > 0)
189  {
190  // fast path
191  semaphore->count--;
192  return 0;
193  }
194  Time expirationTime = UtilsTimeToSimulationTime (UtilsTimespecToTime (*abs_timeout));
195  if (expirationTime <= Simulator::Now ())
196  {
197  // timer already expired when we start.
198  current->err = ETIMEDOUT;
199  return -1;
200  }
201  // setup timer.
202  Time timeoutLeft = expirationTime - Simulator::Now ();
203  while (semaphore->count == 0)
204  {
205  semaphore->waiting.push_back (current);
206  timeoutLeft = current->process->manager->Wait (timeoutLeft);
207  semaphore->waiting.remove (current);
208  if (timeoutLeft.IsZero ())
209  {
210  // timer expired
211  current->err = ETIMEDOUT;
212  return -1;
213  }
214  }
215  semaphore->count--;
216  return 0;
217 }
218 int dce_sem_getvalue (sem_t *sem, int *sval)
219 {
220  Thread *current = Current ();
221  NS_LOG_FUNCTION (current << UtilsGetNodeId () << sem);
222  NS_ASSERT (current != 0);
223 
224  struct Semaphore *semaphore = SearchSemaphore (sem);
225  if (semaphore == 0)
226  {
227  current->err = EINVAL;
228  return -1;
229  }
230  *sval = semaphore->count;
231  return 0;
232 }