]> rtime.felk.cvut.cz Git - frescor/frsh.git/blob - frsh_api/frsh_sharedobj.c
Remove "Setup" header from tests
[frescor/frsh.git] / frsh_api / frsh_sharedobj.c
1 /**
2  * @file   frsh_sharedobj.c
3  * @author Dario Faggioli <faggioli@gandalf.sssup.it>
4  *
5  * @brief  FRSH shared objects related functions.
6  *
7  *
8  */
9 #include <fres_contract.h>
10 #include <fres_contract_idl.h>
11 #include <frsh_error.h>
12 #include <fres_blocks.h>
13 #include <frsh_core.h>
14 #include <fres_sharedobj.h>
15
16 int frsh_sharedobj_init
17   (const char *obj_label,
18    frsh_sharedobj_kind_t obj_kind,
19    frsh_sharedobj_handle_t *obj_handle,
20    frsh_mutex_t *mutex)
21 {
22         if (!obj_handle)
23                 return FRSH_ERR_BAD_ARGUMENT;
24
25         /* In this implementation external mutex is not supported, *
26          * use frsh_sharedobj_get_mutex instead.                   */
27         if (mutex)
28                 return FRSH_ERR_BAD_ARGUMENT;
29
30         *obj_handle = fres_sharedobj_new(obj_label, obj_kind);
31         if (!(*obj_handle)) goto err;
32
33         return 0;
34 err:
35         return errno;
36 }
37
38 int frsh_sharedobj_get_handle
39   (char *obj_label,
40    frsh_sharedobj_handle_t *obj_handle)
41 {
42         if (!obj_label || !obj_handle)
43                 return FRSH_ERR_BAD_ARGUMENT;
44
45         *obj_handle = fres_sharedobj_get_label(obj_label);
46         if (!(*obj_handle)) goto err;
47
48         return 0;
49 err:
50         return errno;
51 }
52
53 int frsh_sharedobj_get_mutex
54   (frsh_sharedobj_handle_t obj_handle,
55    frsh_mutex_t **mutex)
56 {
57         if (!obj_handle || !mutex)
58                 return FRSH_ERR_BAD_ARGUMENT;
59
60         *mutex = &obj_handle->mutex;
61
62         return 0;
63 }
64
65 int frsh_sharedobj_get_obj_kind
66   (frsh_sharedobj_handle_t obj_handle,
67    frsh_sharedobj_kind_t *obj_kind)
68 {
69         if (!obj_handle || !obj_kind)
70                 return FRSH_ERR_BAD_ARGUMENT;
71
72         *obj_kind = obj_handle->kind;
73
74         return 0;
75 }
76
77 int frsh_sharedobj_remove(frsh_sharedobj_handle_t obj_handle)
78 {
79         if (!obj_handle)
80                 return FRSH_ERR_BAD_ARGUMENT;
81
82         return fres_sharedobj_destroy(obj_handle);
83 }
84
85 /* Critical Sections. */
86
87 int frsh_csect_init
88   (frsh_sharedobj_handle_t obj_handle,
89    frsh_rel_time_t wcet,
90    frsh_csect_t *csect)
91 {
92         if (!obj_handle || !csect)
93                 return FRSH_ERR_BAD_ARGUMENT;
94
95         csect->op_kind = FRSH_CSOK_UNCHECKED;
96         strncpy(csect->obj_label,
97                 obj_handle->label,
98                 sizeof(obj_handle->label));
99         csect->wcet = wcet;
100         csect->blocking = wcet;
101         csect->op = NULL;
102         csect->areas.size = 0;
103
104         return 0;
105 }
106
107 int frsh_csect_get_sharedobj_handle
108   (const frsh_csect_t *csect,
109    frsh_sharedobj_handle_t *obj_handle)
110 {
111         if (!obj_handle || !csect)
112                 return FRSH_ERR_BAD_ARGUMENT;
113
114         *obj_handle = fres_sharedobj_get_label(csect->obj_label);
115
116         return 0;
117 }
118
119 int frsh_csect_get_wcet
120   (const frsh_csect_t *csect,
121    frsh_rel_time_t *wcet)
122 {
123         if (!csect || !wcet)
124                 return FRSH_ERR_BAD_ARGUMENT;
125
126         *wcet = csect->wcet;
127
128         return 0;
129 }
130
131 int frsh_csect_get_blocking_time
132   (const frsh_csect_t *csect,
133    fosa_rel_time_t *blocking)
134 {
135         if (!csect || !blocking)
136                 return FRSH_ERR_BAD_ARGUMENT;
137
138         *blocking = csect->blocking;
139
140         return 0;
141 }
142
143 int frsh_csect_get_op_kind
144   (const frsh_csect_t *csect,
145    frsh_csect_op_kind_t *op_kind)
146 {
147         if (!csect || !op_kind)
148                 return FRSH_ERR_BAD_ARGUMENT;
149
150         *op_kind = csect->op_kind;
151
152         return 0;
153 }
154
155 int frsh_csect_get_read_op
156   (const frsh_csect_t *csect,
157    frsh_csect_op_t *op)
158 {
159         if (!csect ||
160             !op ||
161             csect->op_kind != FRSH_CSOK_READ)
162                 return FRSH_ERR_BAD_ARGUMENT;
163
164         *op = csect->op;
165
166         return 0;
167 }
168
169 int frsh_csect_get_write_op
170   (const frsh_csect_t *csect,
171    frsh_csect_op_t *op,
172    frsh_memory_areas_t *areas)
173 {
174         int i;
175
176         if (!csect ||
177             !op ||
178             !areas ||
179             csect->op_kind != FRSH_CSOK_WRITE)
180                 return FRSH_ERR_BAD_ARGUMENT;
181
182         *op = csect->op;
183         areas->size = csect->areas.size;
184
185         for (i = 0; i < areas->size; i++)
186                 areas->memory_areas[i] = csect->areas.memory_areas[i];
187
188         return 0;
189 }
190
191 int frsh_csect_register_read_op
192   (frsh_csect_t *csect,
193    frsh_csect_op_t op)
194 {
195         if (!csect || !op)
196                 return FRSH_ERR_BAD_ARGUMENT;
197
198         csect->op_kind = FRSH_CSOK_READ;
199         csect->op = op;
200
201         /* Account for protection overheads: NOT IMPLEMENTED! */
202         /* csect->blocking = fosa_rel_time_add(csect->wcet, ); */
203         csect->blocking = csect->wcet;
204
205         return 0;
206 }
207
208 int frsh_csect_register_write_op
209   (frsh_csect_t *csect,
210    frsh_csect_op_t op,
211    const frsh_memory_areas_t *areas)
212 {
213         int i;
214
215         if (!csect || !op)
216                 return FRSH_ERR_BAD_ARGUMENT;
217
218         if (areas->size <= 0 || areas->size > FRSH_MAX_N_MEMORY_AREAS)
219                 return FRSH_ERR_BAD_ARGUMENT;
220
221         /* TODO:
222          *  Check for the shared object associated with this
223          *  critical section not to be UNPROTECTED;
224          */
225
226         csect->areas.size = areas->size;
227         csect->op_kind = FRSH_CSOK_WRITE;
228         csect->op = op;
229
230         for (i = 0; i< areas->size; i++)
231                 csect->areas.memory_areas[i] = areas->memory_areas[i];
232
233         /* Account for protection and rollback overheads: NOT IMPLEMENTED! */
234         /* csect->blocking = fosa_rel_time_add(csect->wcet, ); */
235         csect->blocking = csect->wcet;
236
237         return 0;
238 }
239
240 int frsh_csect_invoke
241   (const frsh_csect_t *csect,
242    const void *input_arg,
243    void *output_arg)
244 {
245         int i, jumped, ret = 0;
246         frsh_memory_areas_t storage = { .size = 0 };
247         frsh_sharedobj_handle_t obj_handle;
248         fosa_mutex_t *obj_mutex;
249         fosa_clock_id_t clockid;
250         fosa_signal_t signal;
251         fosa_signal_info_t siginfo;
252
253         if (!csect) {
254                 ret = FRSH_ERR_BAD_ARGUMENT;
255                 goto out;
256         }
257
258         obj_handle = fres_sharedobj_get_label(csect->obj_label);
259         if (!obj_handle) {
260                 ret = errno;
261                 goto out;
262         }
263         ret = frsh_sharedobj_get_mutex(obj_handle, &obj_mutex);
264         if (ret) goto out;
265         ret = fosa_mutex_lock(obj_mutex);
266         if (ret) goto out;
267
268         siginfo.sival_ptr = (void*) (&(obj_handle->context));
269         ret = fosa_long_jump_install_handler(&signal, NULL);
270         if (ret) goto out_unlock;
271
272         /* Prepare the WCET timer. */
273         ret = fosa_thread_get_cputime_clock(fosa_thread_self() ,&clockid);
274         if (ret) goto out_unlock;
275         ret = fosa_timer_create_with_receiver(clockid,
276                                               signal,
277                                               siginfo,
278                                               &obj_handle->wcet_timer,
279                                               fosa_thread_self());
280         if (ret) goto out_unlock;
281         ret = fosa_rel_timer_arm(obj_handle->wcet_timer, &csect->wcet);
282         if (ret) goto out_disarm;
283
284         /* Backup memory areas. */
285         if (csect->op_kind == FRSH_CSOK_WRITE) {
286                 for (i = 0; i < csect->areas.size; i++) {
287                         storage.memory_areas[i].size =
288                                 csect->areas.memory_areas[i].size;
289                         storage.memory_areas[i].area =
290                                 malloc(csect->areas.memory_areas[i].size);
291                         if (!storage.memory_areas[i].area) {
292                                 ret = errno;
293                                 goto out_disarm;
294                         }
295                         if (!memcpy(storage.memory_areas[i].area,
296                                     csect->areas.memory_areas[i].area,
297                                     csect->areas.memory_areas[i].size)) {
298                                 ret = errno;
299                                 goto out_disarm;
300                         }
301                         storage.size++;
302                 }
303         }
304
305         ret = fosa_long_jump_save_context(&obj_handle->context);
306         if (ret) goto out_disarm;
307         ret = fosa_long_jump_was_performed(&obj_handle->context, &jumped);
308         if (ret) goto out_disarm;
309
310         if (!jumped) {
311                 /* Invoke the operation. */
312                 csect->op(input_arg,output_arg);
313
314                 /* Leave the critical section normally. */
315                 goto out_disarm;
316         }
317
318         ret = FRSH_ERR_BUDGET_EXPIRED;
319
320         /* Restore backed-up memory areas. */
321         if (csect->op_kind == FRSH_CSOK_WRITE) {
322                 for (i = 0; i < csect->areas.size; i++)
323                         if (!memcpy(csect->areas.memory_areas[i].area,
324                                     storage.memory_areas[i].area,
325                                     csect->areas.memory_areas[i].size)) {
326                                 ret = errno;
327                                 goto out_unlock;
328                         }
329         }
330
331 out_disarm:
332         fosa_timer_disarm(obj_handle->wcet_timer, NULL);
333         fosa_timer_delete(obj_handle->wcet_timer);
334
335         for (i = 0; i < storage.size; i++)
336                 if (storage.memory_areas[i].area)       /* Uneeded ? */
337                         free(storage.memory_areas[i].area);
338
339 out_unlock:
340         fosa_mutex_unlock(obj_mutex);
341 out:
342         return ret;
343 }
344
345 /* Contract Parameters. */
346
347 int frsh_contract_set_csects
348   (frsh_contract_t *contract,
349    const frsh_csects_group_t *critical_sections)
350 {
351         fres_block_csects *c;
352         int i, len, ret;
353
354         if (!contract || !*contract || !critical_sections)
355                 return FRSH_ERR_BAD_ARGUMENT;
356
357         if (critical_sections->size < 0 ||
358             critical_sections->size > FRSH_MAX_N_CRITICAL_SECTIONS)
359                 return FRSH_ERR_BAD_ARGUMENT;
360
361         c = malloc(sizeof(*c));
362         if (!c) return FOSA_ENOMEM;
363
364         len = critical_sections->size;
365         c->sections._length = len;
366         c->sections._maximum = len;
367         c->sections._buffer = CORBA_sequence_frsh_csect_runtime_allocbuf(len);
368         for (i = 0; i < len; i++)
369                 memcpy(&c->sections._buffer[i],
370                        &critical_sections->csects[i],
371                        sizeof(c->sections._buffer[i]));
372
373         fres_contract_del_csects(*contract);
374         ret = fres_contract_add_csects(*contract, c);
375
376         if (ret) {
377                 free(c);
378                 return errno;
379         }
380
381         return 0;
382 }
383
384 int frsh_contract_get_csects
385   (const frsh_contract_t *contract,
386    frsh_csects_group_t *critical_sections)
387 {
388         fres_block_csects *c;
389         int i;
390
391         if (!contract || !*contract || !critical_sections)
392                 return FRSH_ERR_BAD_ARGUMENT;
393
394         c = fres_contract_get_csects(*contract);
395
396         critical_sections->size = c->sections._length;
397         for (i = 0; i < critical_sections->size; i++)
398                 memcpy(&critical_sections->csects[i],
399                        &c->sections._buffer[i],
400                        sizeof(critical_sections->csects[i]));
401
402         return 0;
403 }
404