Subversion Repositories shark

Rev

Rev 941 | Rev 964 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
221 giacomo 1
//=====================================================================
2
//       FFFFFFIII   RRRRR      SSTTTTTTT
3
//      FF         IIR   RR    SS
4
//     FF           IR        SS
5
//    FFFFFF         RRRR    SSSSST      
6
//   FF       FI       RRR  SS
7
//  FF         II     RRR  SS
8
// FF           IIIIIR    RS 
9
//       
10
// Basic FSF(FIRST Scheduling Framework) contract management
11
// S.Ha.R.K. Implementation
12
//=====================================================================
13
 
908 trimarchi 14
#include "fsf.h"
808 trimarchi 15
#include "fsf_server.h"
16
#include <kernel/descr.h>
17
#include <kernel/func.h>
18
#include <pistar.h>
221 giacomo 19
 
808 trimarchi 20
struct hash_entry {
21
  mutex_t mx;
868 trimarchi 22
  FSF_SHARED_OBJ_HANDLE_T_OPAQUE id;
808 trimarchi 23
};
24
 
25
 
868 trimarchi 26
#define MAX_HASH_ENTRY FSF_MAX_N_SHARED_OBJECTS 
808 trimarchi 27
struct  hash_entry htable[MAX_HASH_ENTRY];
28
 
29
 
30
/*----------------------------------------------------------------------*/
31
/* hash_fun() : address hash table                                      */
32
/*----------------------------------------------------------------------*/
868 trimarchi 33
static int hash_fun(fsf_shared_obj_id_t id)
808 trimarchi 34
{
35
    return (*id % MAX_HASH_ENTRY);
36
}
37
 
811 trimarchi 38
void fsf_register_shared_object(void) {
39
int i=0;
40
// Init Hash table
41
//kern_printf("(IT SO)\n");
42
for (i=0; i<MAX_HASH_ENTRY; i++) {
43
  htable[i].id=-1;
808 trimarchi 44
 
811 trimarchi 45
}
46
 
47
}
881 trimarchi 48
int fsf_init() {
811 trimarchi 49
 
881 trimarchi 50
  FSF_start_service_task();
941 trimarchi 51
  FSF_init_synch_obj_layer();
881 trimarchi 52
}
53
 
54
 
221 giacomo 55
int fsf_initialize_contract
56
  (fsf_contract_parameters_t *contract)
57
{
58
  struct timespec default_deadline = FSF_DEFAULT_DEADLINE;
59
 
60
  /* Check */
868 trimarchi 61
  if (!contract) return  FSF_ERR_BAD_ARGUMENT;
221 giacomo 62
 
63
  /* Set to default value */
64
  NULL_TIMESPEC(&contract->budget_min);
65
  NULL_TIMESPEC(&contract->budget_max);
66
  NULL_TIMESPEC(&contract->period_min);
67
  NULL_TIMESPEC(&contract->period_max);
68
 
69
  contract->workload = FSF_DEFAULT_WORKLOAD;
70
 
868 trimarchi 71
  contract->policy = FSF_DEFAULT_SCHED_POLICY;
221 giacomo 72
 
73
  contract->d_equals_t = FSF_DEFAULT_D_EQUALS_T;
74
 
75
  TIMESPEC_ASSIGN(&contract->deadline,&default_deadline);
76
 
77
  contract->budget_overrun_sig_notify = 0;
78
  memset(&contract->budget_overrun_sig_value,0,sizeof(union sigval));
79
 
80
  contract->deadline_miss_sig_notify = 0;
81
  memset(&contract->deadline_miss_sig_value,0,sizeof(union sigval));
82
 
83
  contract->granularity = FSF_DEFAULT_GRANULARITY;
84
  contract->utilization_set.size = 0;
85
  contract->quality = FSF_DEFAULT_QUALITY;
86
  contract->importance = FSF_DEFAULT_IMPORTANCE;
87
 
88
  contract->preemption_level = 0;
89
  contract->critical_sections.size = 0;
90
 
91
  return 0;
92
 
93
}
94
 
95
int fsf_set_contract_basic_parameters
96
  (fsf_contract_parameters_t *contract,
97
   const struct timespec  *budget_min,
868 trimarchi 98
   const struct timespec  *period_max,  
221 giacomo 99
   fsf_workload_t          workload)
100
{
101
 
868 trimarchi 102
  if (!contract) return  FSF_ERR_BAD_ARGUMENT;
221 giacomo 103
 
940 trimarchi 104
  if (budget_min->tv_sec < 0 || budget_min->tv_nsec > 1000000000)
105
     return FSF_ERR_BAD_ARGUMENT;
106
 
107
  if (period_max->tv_sec < 0 || period_max->tv_nsec > 1000000000)
108
     return FSF_ERR_BAD_ARGUMENT;
109
 
874 trimarchi 110
  if (budget_min && (budget_min->tv_sec!=0 || budget_min->tv_nsec!=0)) {
868 trimarchi 111
     TIMESPEC_ASSIGN(&contract->budget_min,budget_min);
112
     TIMESPEC_ASSIGN(&contract->budget_max,budget_min);
874 trimarchi 113
  } else return FSF_ERR_BAD_ARGUMENT;
114
 
115
  if (period_max && (period_max->tv_sec!=0 || period_max->tv_nsec!=0)) {
868 trimarchi 116
     TIMESPEC_ASSIGN(&contract->period_max,period_max);
117
     TIMESPEC_ASSIGN(&contract->period_min,period_max);
874 trimarchi 118
  } else return FSF_ERR_BAD_ARGUMENT;
119
 
120
  switch(workload) {
121
     case FSF_INDETERMINATE:
122
     case FSF_BOUNDED:
123
     case FSF_OVERHEAD:
124
        contract->workload = workload;
125
        break;
126
     default: return FSF_ERR_BAD_ARGUMENT;
868 trimarchi 127
  }
221 giacomo 128
 
874 trimarchi 129
 
221 giacomo 130
  return 0;
131
 
132
}
133
 
134
int fsf_get_contract_basic_parameters
135
  (const fsf_contract_parameters_t *contract,
136
   struct timespec  *budget_min,
137
   struct timespec  *period_max,
138
   fsf_workload_t   *workload)
139
{
140
 
874 trimarchi 141
  if (!contract) return FSF_ERR_BAD_ARGUMENT;
221 giacomo 142
 
143
  TIMESPEC_ASSIGN(budget_min,&contract->budget_min);
868 trimarchi 144
  TIMESPEC_ASSIGN(period_max,&contract->period_max);
221 giacomo 145
 
146
  *workload = contract->workload;
147
 
148
  return 0;
149
 
150
}
151
 
152
int fsf_set_contract_timing_requirements
153
  (fsf_contract_parameters_t *contract,
154
   bool                   d_equals_t,
155
   const struct timespec *deadline,
156
   int                    budget_overrun_sig_notify,
157
   union sigval           budget_overrun_sig_value,
158
   int                    deadline_miss_sig_notify,
159
   union sigval           deadline_miss_sig_value)
160
{
161
 
868 trimarchi 162
  if (!contract) return FSF_ERR_BAD_ARGUMENT;
908 trimarchi 163
  if ((d_equals_t==true && deadline != FSF_NULL_DEADLINE) ||
164
      (d_equals_t==false && deadline == FSF_NULL_DEADLINE))
874 trimarchi 165
     return FSF_ERR_BAD_ARGUMENT;
908 trimarchi 166
  if (deadline != FSF_NULL_DEADLINE && TIMESPEC_A_GT_B(deadline, &contract->period_max))
874 trimarchi 167
     return FSF_ERR_BAD_ARGUMENT;
221 giacomo 168
 
169
  contract->d_equals_t = d_equals_t;
170
 
171
  if (deadline) TIMESPEC_ASSIGN(&contract->deadline,deadline);
172
 
173
  contract->budget_overrun_sig_notify = budget_overrun_sig_notify;
174
  contract->budget_overrun_sig_value = budget_overrun_sig_value;
175
  contract->deadline_miss_sig_notify = deadline_miss_sig_notify;
176
  contract->deadline_miss_sig_value = deadline_miss_sig_value;
177
 
178
  return 0;
179
 
180
}
181
 
182
int fsf_get_contract_timing_requirements
183
  (const fsf_contract_parameters_t *contract,
184
   bool                            *d_equals_t,
185
   struct timespec                 *deadline,
186
   int                             *budget_overrun_sig_notify,
187
   union sigval                    *budget_overrun_sig_value,
188
   int                             *deadline_miss_sig_notify,
189
   union sigval                    *deadline_miss_sig_value)
190
{
191
 
868 trimarchi 192
  if (!contract) return  FSF_ERR_BAD_ARGUMENT;
221 giacomo 193
 
194
  *d_equals_t = contract->d_equals_t;
195
 
196
  TIMESPEC_ASSIGN(deadline,&contract->deadline);
197
 
198
  *budget_overrun_sig_notify = contract->budget_overrun_sig_notify;
199
  *budget_overrun_sig_value = contract->budget_overrun_sig_value;
200
  *deadline_miss_sig_notify = contract->deadline_miss_sig_notify;
201
  *deadline_miss_sig_value = contract->deadline_miss_sig_value;
202
 
203
  return 0;
204
 
205
}
206
 
868 trimarchi 207
int
208
fsf_set_contract_reclamation_parameters
209
  (fsf_contract_parameters_t   *contract,
210
   const struct timespec       *budget_max,
211
   const struct timespec       *period_min,
221 giacomo 212
   fsf_granularity_t            granularity,
868 trimarchi 213
   const fsf_utilization_set_t *utilization_set,
221 giacomo 214
   int                          quality,
215
   int                          importance)
216
{
217
 
868 trimarchi 218
  if (!contract) return  FSF_ERR_BAD_ARGUMENT;
221 giacomo 219
 
940 trimarchi 220
  if (budget_max->tv_sec < 0 || budget_max->tv_nsec > 1000000000)
221
     return FSF_ERR_BAD_ARGUMENT;
222
 
223
  if (period_min->tv_sec < 0 || period_min->tv_nsec > 1000000000)
224
     return FSF_ERR_BAD_ARGUMENT;
225
 
221 giacomo 226
  contract->granularity = granularity;
227
 
228
  if (utilization_set) memcpy(&contract->utilization_set,utilization_set,sizeof(fsf_utilization_set_t));
868 trimarchi 229
 
230
  if (budget_max) TIMESPEC_ASSIGN(&contract->budget_max,budget_max);
231
  if (period_min) TIMESPEC_ASSIGN(&contract->period_min,period_min);
232
 
221 giacomo 233
  contract->quality = quality;
234
  contract->importance = importance;
235
 
236
  return 0;
237
 
238
}
239
 
240
int fsf_get_contract_reclamation_parameters
241
  (const fsf_contract_parameters_t *contract,
868 trimarchi 242
   struct timespec                 *budget_max,
243
   struct timespec                 *period_min,
221 giacomo 244
   fsf_granularity_t               *granularity,
245
   fsf_utilization_set_t           *utilization_set,
246
   int                             *quality,
247
   int                             *importance)
248
{
249
 
868 trimarchi 250
  if (!contract) return FSF_ERR_BAD_ARGUMENT;
221 giacomo 251
 
252
  *granularity = contract->granularity;
253
 
254
  memcpy(utilization_set,&contract->utilization_set,sizeof(fsf_utilization_set_t));
868 trimarchi 255
 
256
  TIMESPEC_ASSIGN(budget_max,&contract->budget_max);
257
  TIMESPEC_ASSIGN(period_min,&contract->period_min);
221 giacomo 258
 
259
  *quality = contract->quality;
260
  *importance = contract->importance;
261
 
262
  return 0;
263
 
264
}
265
 
266
int fsf_set_contract_synchronization_parameters
267
  (fsf_contract_parameters_t     *contract,
268
   const fsf_critical_sections_t *critical_sections)
269
{
270
 
868 trimarchi 271
  if (!contract) return FSF_ERR_BAD_ARGUMENT;
221 giacomo 272
 
273
  if (critical_sections) memcpy(&contract->critical_sections,critical_sections,sizeof(fsf_critical_sections_t));
274
 
275
  return 0;
276
 
277
}
278
 
279
int
280
fsf_get_contract_synchronization_parameters
281
  (const fsf_contract_parameters_t *contract,
282
   fsf_critical_sections_t         *critical_sections)
283
{
284
 
868 trimarchi 285
  if (!contract) return FSF_ERR_BAD_ARGUMENT;
286
 
221 giacomo 287
  memcpy(critical_sections,&contract->critical_sections,sizeof(fsf_critical_sections_t));
288
 
289
  return 0;
290
 
291
}
292
 
868 trimarchi 293
int
294
fsf_set_contract_scheduling_policy
221 giacomo 295
  (fsf_contract_parameters_t *contract,
868 trimarchi 296
   fsf_sched_policy_t         sched_policy)
221 giacomo 297
{
298
 
868 trimarchi 299
  if (!contract) return  FSF_ERR_BAD_ARGUMENT;
221 giacomo 300
 
868 trimarchi 301
  contract->policy = sched_policy;
221 giacomo 302
 
303
  return 0;
304
 
305
}
306
 
307
int
868 trimarchi 308
fsf_get_contract_scheduling_policy
221 giacomo 309
  (const fsf_contract_parameters_t *contract,
868 trimarchi 310
   fsf_sched_policy_t              *sched_policy)
221 giacomo 311
{
312
 
868 trimarchi 313
  if (!contract) return FSF_ERR_BAD_ARGUMENT;
221 giacomo 314
 
868 trimarchi 315
  *sched_policy = contract->policy;
221 giacomo 316
 
317
  return 0;
318
 
319
}
320
 
868 trimarchi 321
/* OLD VERSION
808 trimarchi 322
// mutex lock function
221 giacomo 323
 
808 trimarchi 324
int fsf_lock_object(fsf_shared_operation_t *op) {
325
  int index, oldindex;
811 trimarchi 326
 
327
  index=hash_fun(&(op->obj_id));  
328
  //kern_printf("index %d, htableid %d, obj_op_id %d", index, htable[index].id,op->obj_id);
221 giacomo 329
 
808 trimarchi 330
  if (htable[index].id!=op->obj_id) {
331
    oldindex=index;
332
    index = (index + 1) % MAX_HASH_ENTRY;
333
    // find
811 trimarchi 334
    while (htable[index].id != op->obj_id && index!=oldindex) index=(index+1) % MAX_HASH_ENTRY;
808 trimarchi 335
    if (index==oldindex) return -1;
336
  }
811 trimarchi 337
  //kern_printf("(SO LK)");
808 trimarchi 338
  // we need a special implementation for mutex_lock ... additional parameter
829 giacomo 339
  return PISTAR_lock(FSF_get_shared_object_level(), &htable[index].mx,TIMESPEC2USEC(&op->wcet));
808 trimarchi 340
 
341
}
342
 
343
int fsf_unlock_object(fsf_shared_operation_t *op) {
344
 
345
  int index, oldindex;
346
 
347
  index=hash_fun(&op->obj_id);  
348
 
349
  if (htable[index].id!=op->obj_id) {
350
    oldindex=index;
351
    index = (index + 1) % MAX_HASH_ENTRY;
352
    // find
811 trimarchi 353
    while (htable[index].id != op->obj_id && index!=oldindex) index=(index+1) % MAX_HASH_ENTRY;
808 trimarchi 354
    if (index==oldindex) return -1;
355
  }
811 trimarchi 356
  //kern_printf("UNLOCK index %d", index);
357
 
808 trimarchi 358
  return mutex_unlock(&htable[index].mx);
359
 
360
 
361
 
362
}
363
 
868 trimarchi 364
*/
365
 
366
int fsf_init_shared_object
367
   (fsf_shared_obj_id_t      id,
368
    fsf_shared_obj_handle_t *obj,
369
    pthread_mutex_t         *mutex) {
808 trimarchi 370
  int index;
371
  int oldindex;
372
  PISTAR_mutexattr_t a;
811 trimarchi 373
  SYS_FLAGS f;
808 trimarchi 374
 
375
  PISTAR_mutexattr_default(a);
811 trimarchi 376
  //kern_printf("(SI SO)\n");
377
  f=kern_fsave();
829 giacomo 378
 
868 trimarchi 379
  index=hash_fun(id);
811 trimarchi 380
  //kern_printf("Index %d Hash %d", index, htable[index].id);
829 giacomo 381
 
868 trimarchi 382
  if (htable[index].id == index) {
829 giacomo 383
        kern_frestore(f);
384
        return -1;
385
  }
386
 
808 trimarchi 387
  if (htable[index].id>=0) {
388
    oldindex=index;
389
    index = (index + 1) % MAX_HASH_ENTRY;
390
    // collision detection
811 trimarchi 391
    while (htable[index].id >=0 && index!=oldindex) index=(index+1) % MAX_HASH_ENTRY;
808 trimarchi 392
    // table is full
825 trimarchi 393
    if (index==oldindex) {
394
        kern_frestore(f);
829 giacomo 395
        return -1;
825 trimarchi 396
    }
808 trimarchi 397
  }
829 giacomo 398
 
868 trimarchi 399
  //obj->size=0;
829 giacomo 400
 
808 trimarchi 401
  mutex_init(&(htable[index]).mx, &a);
868 trimarchi 402
  mutex=&(htable[index]).mx;
403
  htable[index].id=index;
404
  *obj=*id;
811 trimarchi 405
  kern_frestore(f);
829 giacomo 406
 
407
  return 0;
408
 
811 trimarchi 409
  //kern_printf("(EI SO)\n");
808 trimarchi 410
}
411
 
868 trimarchi 412
/* OLD VERSION
808 trimarchi 413
// Declare an operation
414
// This function is used to declare that a shared object has
415
//    a synchronized operation on it.
416
// It checks if another operation with the same id has already been
417
//    declared; if so, return false (-1).
418
// The obj_id field of the operation is set equal to the shared object id.
419
// the structure op is copied in the first free element in the array
420
//    shared_op pof the structure obj. If there are no more free element,
421
//    returns -1.
422
// Returns 0 if the operation has been completed, -1 otherwise.
423
 
424
int fsf_declare_shared_object_operation(fsf_shared_object_t *obj,
425
                                        fsf_shared_operation_t *op) {
426
  int i;
825 trimarchi 427
  SYS_FLAGS f;
428
 
429
  f=kern_fsave();
430
 
808 trimarchi 431
  for (i=0; i<obj->size; i++) {
432
    // fail if the operation already declared
825 trimarchi 433
    if (op->op_id==obj->shared_op[i].op_id) {
434
      kern_frestore(f);
808 trimarchi 435
      return -1;    
825 trimarchi 436
    }
808 trimarchi 437
  }
438
 
439
  // fail if the object is full
825 trimarchi 440
  if (obj->size>(FSF_MAX_SHARED_OPERATION-1)) {
441
    kern_frestore(f);
808 trimarchi 442
    return -1;  
825 trimarchi 443
  }
829 giacomo 444
 
823 trimarchi 445
  //kern_printf("(DO SO)");
808 trimarchi 446
  obj->size++;
829 giacomo 447
  obj->shared_op[i].op_id = op->op_id;
448
  TIMESPEC_ASSIGN(&obj->shared_op[i].wcet,&op->wcet);
449
  obj->shared_op[i].obj_id = obj->obj_id;
450
  op->obj_id = obj->obj_id;
451
 
825 trimarchi 452
  kern_frestore(f);  
829 giacomo 453
 
808 trimarchi 454
  return 0;
455
 
456
 
457
}
868 trimarchi 458
*/
808 trimarchi 459
 
868 trimarchi 460
/* OLD VERSION
808 trimarchi 461
int fsf_set_contract_synchronization_parameters(
462
    fsf_contract_parameters_t *contract,
463
    const fsf_shared_operation_t *shared_ops,
464
    size_t op_num)
465
{
466
  if (shared_ops && op_num < FSF_MAX_SHARED_OPERATION)
467
    memcpy(&contract->shared_operations,shared_ops,op_num);
468
  else return -1;
469
 
470
  return 0;
471
}
868 trimarchi 472
*/
954 trimarchi 473
 
474
// MARTE IMPLEMENTATION SPECIFIC MODULE
475
 
476
// The operations defined in this module are of optional use. They
477
// only work in the fixed priority implementation, and they may be
478
// used to enhance the behavior of the applications running under the
479
// fsf scheduler.
480
 
481
//// The definition of this type is in fsf_basic_types.h
482
//
483
//typedef unsigned long      fsf_preemption_level_t;
484
//                           // range 1..2**32-1
485
 
486
 
487
//fsf_set_contract_preemption_level: The operation updates the
488
//specified contract parameters object by setting its preemption level
489
//to the specified input parameter.
490
 
491
int
492
fsf_set_contract_preemption_level
493
  (fsf_contract_parameters_t     *contract,
494
   fsf_preemption_level_t         preemption_level) {
495
  return 0;
496
}
497
 
498
 
499
//fsf_get_contract_preemption_level: The operation obtains from the
500
//specified contract parameters object its preemption level and copies
501
//it to the place pointed to by the specified input parameter.
502
 
503
int
504
fsf_get_contract_preemption_level
505
  (const fsf_contract_parameters_t *contract,
506
   fsf_preemption_level_t          *preemption_level)  {
507
  return 0;
508
}
509
 
510
 
511
 
512
//fsf_set_service_thread_preemption_level: this function sets the
513
//preemption level of the service thread to the specified value. The
514
//initial preemption level is a configurable parameter
515
 
516
int
517
fsf_set_service_thread_preemption_level
518
  (fsf_preemption_level_t         preemption_level) {
519
  return 0;
520
}
521
 
522
 
523
//fsf_get_service_thread_preemption_level: this function stores the
524
//current preemption level of the service thread in the variable
525
//pointed to by preemption_level
526
 
527
int
528
fsf_get_service_thread_preemption_level
529
  (fsf_preemption_level_t        *preemption_level) {
530
  return 0;
531
}
532
 
533
 
534
 
535
//fsf_thread_exit: There is a limitation in the current version of the
536
//MaRTE implementation that causes the information of a terminated
537
//thread to continue to be stored in the fsf scheduler, and the thread
538
//to continue to be counted in the number of threads. The
539
//fsf_thread_exit operation allows the implementation to delete the
540
//thread's information, and then terminate the thread. Therefore, it
541
//is recommended to use this function to terminate a thread under fsf.
542
 
543
//This operation shall terminate the calling thread, make the value
544
//value_ptr available to any successful join with the terminating
545
//thread, and unbind the thread from its associated server. After
546
//cleaning up the thread management data, it is unbound and the
547
//scheduling policy is changed to fixed priority before the posix
548
//pthread_exit() function is called.
549
 
550
void
551
fsf_thread_exit (void *value_ptr) {
552
  return;
553
}
554
 
555
 
556
 
557
//fsf_set_shared_obj_preemption_level: The operation updates the
558
//specified shared object by setting its preemption level
559
//to the specified input parameter. 
560
//OBSERVATION: if this value is changed being any contract that
561
//uses the resource already accepted, the system's behavior and
562
//particularly the acceptance tests correctness are not garantee
563
//and probably wrong.
564
 
565
int
566
fsf_set_shared_obj_preemption_level
567
  (fsf_shared_obj_handle_t  obj_handle,
568
   fsf_preemption_level_t   preemption_level) {
569
  return 0;
570
}
571
 
572
 
573
 
574
//fsf_get_shared_obj_preemption_level: The operation obtains from the
575
//specified shared object its preemption level and copies
576
//it to the place pointed to by the specified input parameter.
577
 
578
int
579
fsf_get_shared_obj_preemption_level
580
  (fsf_shared_obj_handle_t  obj_handle,
581
   fsf_preemption_level_t  *preemption_level) {
582
  return 0;
583
}