Subversion Repositories shark

Rev

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