Subversion Repositories shark

Rev

Rev 409 | Rev 411 | 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
 
405 trimarchi 14
#include "ll/i386/64bit.h"
15
 
221 giacomo 16
#include "fsf_contract.h"
241 giacomo 17
#include "fsf_server.h"
221 giacomo 18
 
19
#include <pthread.h>
20
#include <stdlib.h>
21
 
407 giacomo 22
//#define FSF_DEBUG
221 giacomo 23
 
410 trimarchi 24
int current_server=0;
407 giacomo 25
server_elem server_list[FSF_MAX_N_SERVERS];
406 giacomo 26
bandwidth_t fsf_max_bw = 0;
405 trimarchi 27
 
241 giacomo 28
int fsf_server_level;
221 giacomo 29
 
406 giacomo 30
int FSF_register_module(int server_level, bandwidth_t max_bw)
224 giacomo 31
{
32
  printk("FSF Module\n");
410 trimarchi 33
  current_server=0;
241 giacomo 34
  fsf_server_level = server_level;
406 giacomo 35
  fsf_max_bw = max_bw;
224 giacomo 36
 
37
  return 0;
38
 
39
}
40
 
221 giacomo 41
/* Convert the contract specification to
42
 * budget parameters
43
 */
241 giacomo 44
int set_SERVER_budget_from_contract
221 giacomo 45
  (const fsf_contract_parameters_t *contract,
46
   int *budget)
47
{
48
 
49
  int local_scheduler_level = 0;
50
 
51
   switch (contract->local_scheduler_id) {
52
     case FSF_SCHEDULER_POSIX:
241 giacomo 53
       local_scheduler_level = POSIXSTAR_register_level(fsf_server_level,5000,32);
221 giacomo 54
       break;
55
     case FSF_SCHEDULER_EDF:
241 giacomo 56
       local_scheduler_level = EDFSTAR_register_level(fsf_server_level);
221 giacomo 57
       break;
58
     case FSF_SCHEDULER_RM:
241 giacomo 59
       local_scheduler_level = RMSTAR_register_level(fsf_server_level);
221 giacomo 60
       break;
334 giacomo 61
     case FSF_SCHEDULER_MPEG:
62
       local_scheduler_level = MPEGSTAR_register_level(fsf_server_level);
63
       break;
221 giacomo 64
   }    
405 trimarchi 65
 
241 giacomo 66
  *budget = SERVER_setbudget(fsf_server_level,
221 giacomo 67
                              TIMESPEC2USEC(&(contract->budget_min)),
68
                              TIMESPEC2USEC(&(contract->period_max)),
69
                              local_scheduler_level,contract->local_scheduler_id);
70
 
71
  return 0;
72
 
73
}
74
 
405 trimarchi 75
int adjust_SERVER_budget
76
   (int budget, const TIME budget_actual,
77
    const TIME period_actual)
221 giacomo 78
{
79
 
241 giacomo 80
  SERVER_adjust_budget(fsf_server_level,
405 trimarchi 81
                       budget_actual,
82
                       period_actual,
241 giacomo 83
                       budget);
221 giacomo 84
 
85
  return 0;
86
 
87
}
88
 
89
/* Admission Test function */
90
int add_contract(const fsf_contract_parameters_t *contract)
91
{
92
  return 0;
93
 
94
}
95
 
410 trimarchi 96
int relink_contract_to_server(const fsf_contract_parameters_t *contract,
97
                              fsf_server_id_t server)
98
{
99
  TIME T,Q;
100
  int i=0;
101
#ifdef FSF_DEBUG
102
  int temp;
103
  kern_printf("(Relink Server %d)",server);
104
#endif
105
  // find contract
106
  while(i<current_server) {
107
    if (server_list[i].server==server) break;
108
    i++;
109
  }
110
 
111
  server_list[i].server=server;
112
  server_list[i].Qs=1;
113
 
114
  T=TIMESPEC2USEC(&contract->period_min);
115
  Q=TIMESPEC2USEC(&contract->budget_max);
116
  mul32div32to32(MAX_BANDWIDTH,Q,T,server_list[current_server].Umax);
117
 
118
  T=TIMESPEC2USEC(&contract->period_max);
119
  server_list[i].Tmax=T;
120
 
121
  Q=TIMESPEC2USEC(&contract->budget_min);
122
  server_list[i].Cmin=Q;
123
 
124
  mul32div32to32(MAX_BANDWIDTH,Q,T,server_list[i].Umin);
125
  server_list[i].U=server_list[i].Umax;
126
 
127
#ifdef FSF_DEBUG
128
  mul32div32to32(server_list[i].Umax,100, MAX_BANDWIDTH, temp);
129
  kern_printf("(Umax %d)",temp);
130
  mul32div32to32(server_list[i].Umin,100, MAX_BANDWIDTH, temp);
131
  kern_printf("(Umin %d)",temp);
132
#endif
133
 
134
 return 0;
135
 
136
}
137
 
221 giacomo 138
int link_contract_to_server(const fsf_contract_parameters_t *contract,
139
                            fsf_server_id_t server)
140
{
405 trimarchi 141
  TIME T,Q;
407 giacomo 142
#ifdef FSF_DEBUG
405 trimarchi 143
  int temp;
407 giacomo 144
 
405 trimarchi 145
  kern_printf("(Link Server %d)",server);
146
#endif
147
 
410 trimarchi 148
  server_list[current_server].server=server;
149
  server_list[current_server].Qs=1;
405 trimarchi 150
 
151
  T=TIMESPEC2USEC(&contract->period_min);
152
  Q=TIMESPEC2USEC(&contract->budget_max);
410 trimarchi 153
  mul32div32to32(MAX_BANDWIDTH,Q,T,server_list[current_server].Umax);
405 trimarchi 154
 
155
  T=TIMESPEC2USEC(&contract->period_max);
410 trimarchi 156
  server_list[current_server].Tmax=T;
405 trimarchi 157
 
158
  Q=TIMESPEC2USEC(&contract->budget_min);
410 trimarchi 159
  server_list[current_server].Cmin=Q;
405 trimarchi 160
 
410 trimarchi 161
  mul32div32to32(MAX_BANDWIDTH,Q,T,server_list[current_server].Umin);
162
  server_list[current_server].U=server_list[current_server].Umax;
221 giacomo 163
 
405 trimarchi 164
#ifdef FSF_DEBUG
410 trimarchi 165
  mul32div32to32(server_list[current_server].Umax,100, MAX_BANDWIDTH, temp);
405 trimarchi 166
  kern_printf("(Umax %d)",temp);
410 trimarchi 167
  mul32div32to32(server_list[current_server].Umin,100, MAX_BANDWIDTH, temp);
405 trimarchi 168
  kern_printf("(Umin %d)",temp);
169
#endif
170
 
171
 
410 trimarchi 172
  current_server++;
221 giacomo 173
  return 0;
174
 
175
}
176
 
177
int remove_contract(fsf_server_id_t server)
178
{
405 trimarchi 179
  int i=0;
180
  // find the contract
410 trimarchi 181
  while(i<current_server) {
405 trimarchi 182
     if (server_list[i].server==server) break;
183
     i++;
184
  }
221 giacomo 185
 
405 trimarchi 186
  // compress the array;
410 trimarchi 187
  while (i<(current_server-1)) {
405 trimarchi 188
     server_list[i].server=server_list[i+1].server;
189
     server_list[i].Umin=server_list[i+1].Umin;
406 giacomo 190
     server_list[i].U=server_list[i+1].Umax;    
405 trimarchi 191
     server_list[i].Umax=server_list[i+1].Umax;
192
     server_list[i].Cmin=server_list[i+1].Cmin;
193
     server_list[i].Tmax=server_list[i+1].Tmax;
194
     server_list[i].Qs=server_list[i+1].Qs;
195
     i++;
196
  }
410 trimarchi 197
  current_server--;
405 trimarchi 198
 
199
 
221 giacomo 200
  return 0;
201
 
202
}
203
 
204
 
205
int fsf_negotiate_contract
206
  (const fsf_contract_parameters_t *contract,
207
   fsf_server_id_t                 *server)
208
{
405 trimarchi 209
  SYS_FLAGS f;
210
  int i=0;
211
  TIME T;
212
  TIME Q;
221 giacomo 213
  /* Check if contract is initialized */
214
  if (!contract) return FSF_ERR_NOT_INITIALIZED;
215
 
216
  /* Admission Test */
217
  if (FSF_ADMISSION_TEST_IS_ENABLED)
218
    if (add_contract(contract))
219
      return FSF_ERR_CONTRACT_REJECTED;
405 trimarchi 220
  f = kern_fsave();
221 giacomo 221
 
241 giacomo 222
  /* SERVER => BUDGET */    
223
  set_SERVER_budget_from_contract(contract,server);
221 giacomo 224
 
225
  #ifdef FSF_DEBUG
226
    kern_printf("(New Server %d)",*server);
227
  #endif
228
 
405 trimarchi 229
  if (*server >= 0) {
221 giacomo 230
    link_contract_to_server(contract,*server);
406 giacomo 231
    if (recalculate_contract(fsf_max_bw)==-1)  {
405 trimarchi 232
       kern_frestore(f);
233
       return FSF_ERR_CREATE_SERVER;
234
    }
235
#ifdef  FSF_DEBUG
236
    kern_printf("(Adjust budget)");
237
#endif    
410 trimarchi 238
    for (i=0; i<current_server; i++) {
405 trimarchi 239
       mul32div32to32(MAX_BANDWIDTH,server_list[i].Cmin,server_list[i].U,T);
240
       #ifdef FSF_DEBUG
241
       kern_printf("(T %ld)", T);
242
       #endif
407 giacomo 243
       if (T<=server_list[i].Tmax) {
244
          server_list[i].actual_budget = server_list[i].Cmin;
245
          server_list[i].actual_period = T;
405 trimarchi 246
          adjust_SERVER_budget(server_list[i].server,server_list[i].Cmin, T);
407 giacomo 247
       } else {
405 trimarchi 248
         mul32div32to32(server_list[i].Tmax,server_list[i].U,MAX_BANDWIDTH,Q);
249
         #ifdef FSF_DEBUG
250
         kern_printf("(Q %ld)", Q);
251
         #endif
407 giacomo 252
         server_list[i].actual_budget = Q;
253
         server_list[i].actual_period = server_list[i].Tmax;
405 trimarchi 254
         adjust_SERVER_budget(server_list[i].server,Q, server_list[i].Tmax);
255
       }
409 trimarchi 256
         server_list[i].U=server_list[i].Umax;
405 trimarchi 257
 
258
    }
259
  }
260
  else  {
261
    kern_frestore(f);
221 giacomo 262
    return FSF_ERR_CREATE_SERVER;
405 trimarchi 263
  }
264
  kern_frestore(f);
265
 
221 giacomo 266
  return 0;
267
 
268
}
269
 
241 giacomo 270
int fsf_create_thread
271
  (fsf_server_id_t    server,
272
   pthread_t         *thread,
273
   pthread_attr_t    *attr,
274
   fsf_thread_code_t  thread_code,
275
   void              *arg,
276
   void              *local_scheduler_arg)
221 giacomo 277
{
278
 
279
  int local_scheduler_level,scheduler_id;
280
 
281
  #ifdef FSF_DEBUG 
267 giacomo 282
    kern_printf("(FSF:Insert thread = %d to Server = %d)",*thread,server);
221 giacomo 283
  #endif
284
 
285
  /* Check if server and thread exsist */
241 giacomo 286
  if (server == NIL)
287
    return FSF_ERR_INVALID_SERVER;
221 giacomo 288
 
241 giacomo 289
  local_scheduler_level = SERVER_get_local_scheduler_level_from_budget(fsf_server_level,server);
290
  scheduler_id = SERVER_get_local_scheduler_id_from_budget(fsf_server_level,server);
221 giacomo 291
 
292
  /* Check if thread is already bind */
293
  switch (scheduler_id) {
294
    case FSF_SCHEDULER_POSIX:
295
 
298 giacomo 296
      nrt_task_def_arg(*(NRT_TASK_MODEL *)(local_scheduler_arg),arg);
297
      nrt_task_def_level(*(NRT_TASK_MODEL *)(local_scheduler_arg),local_scheduler_level);
221 giacomo 298
 
298 giacomo 299
      *thread = task_create("POSIXSTAR", thread_code, local_scheduler_arg, NULL);
267 giacomo 300
      if (*thread == NIL) {
301
        #ifdef FSF_DEBUG
302
          kern_printf("(FSF:Error creating thread)");
303
        #endif
241 giacomo 304
        return FSF_ERR_CREATE_THREAD;
267 giacomo 305
      }
221 giacomo 306
 
241 giacomo 307
      POSIXSTAR_setbudget(local_scheduler_level, *thread, (int)(server));
234 giacomo 308
 
221 giacomo 309
    break;
310
    case FSF_SCHEDULER_EDF:
311
 
250 giacomo 312
      hard_task_def_arg(*(HARD_TASK_MODEL *)(local_scheduler_arg),arg);
313
      hard_task_def_level(*(HARD_TASK_MODEL *)(local_scheduler_arg),local_scheduler_level);
314
 
315
      *thread = task_create("EDFSTAR", thread_code, local_scheduler_arg, NULL);
316
      if (*thread == NIL)
317
        return FSF_ERR_CREATE_THREAD;
318
 
319
      EDFSTAR_setbudget(local_scheduler_level, *thread, (int)(server));
320
 
221 giacomo 321
      break;
235 giacomo 322
 
221 giacomo 323
    case FSF_SCHEDULER_RM:
235 giacomo 324
 
273 giacomo 325
      hard_task_def_arg(*(HARD_TASK_MODEL *)(local_scheduler_arg),arg);
326
      hard_task_def_level(*(HARD_TASK_MODEL *)(local_scheduler_arg),local_scheduler_level);
327
 
328
      *thread = task_create("RMSTAR", thread_code, local_scheduler_arg, NULL);
329
      if (*thread == NIL)
330
        return FSF_ERR_CREATE_THREAD;
331
 
332
      RMSTAR_setbudget(local_scheduler_level, *thread, (int)(server));
333
 
334
      break;
334 giacomo 335
    case FSF_SCHEDULER_MPEG:
336
 
337
      hard_task_def_arg(*(HARD_TASK_MODEL *)(local_scheduler_arg),arg);
338
      hard_task_def_level(*(HARD_TASK_MODEL *)(local_scheduler_arg),local_scheduler_level);
339
 
338 giacomo 340
      *thread = task_create("MPEGSTAR", thread_code, local_scheduler_arg, NULL);
334 giacomo 341
      if (*thread == NIL)
342
        return FSF_ERR_CREATE_THREAD;
343
 
344
      MPEGSTAR_setbudget(local_scheduler_level, *thread, (int)(server));
345
 
346
      break;
347
 
221 giacomo 348
    default:
241 giacomo 349
      return FSF_ERR_INVALID_SERVER;
221 giacomo 350
      break;
351
  }
352
 
353
  return 0;
354
 
355
}
356
 
357
int fsf_get_server
358
  (fsf_server_id_t *server,
359
   pthread_t       thread)
360
{
361
  int local_scheduler_level, scheduler_id;
362
 
241 giacomo 363
  local_scheduler_level = SERVER_get_local_scheduler_level_from_pid(fsf_server_level,thread);
364
  scheduler_id = SERVER_get_local_scheduler_id_from_pid(fsf_server_level, thread);
221 giacomo 365
 
366
  switch (scheduler_id) {
367
    case FSF_SCHEDULER_POSIX:  
368
      return POSIXSTAR_getbudget(local_scheduler_level,thread);
369
    case FSF_SCHEDULER_EDF:
235 giacomo 370
      return EDFSTAR_getbudget(local_scheduler_level,thread);
221 giacomo 371
    case FSF_SCHEDULER_RM:
235 giacomo 372
      return RMSTAR_getbudget(local_scheduler_level,thread);
334 giacomo 373
    case FSF_SCHEDULER_MPEG:
374
      return MPEGSTAR_getbudget(local_scheduler_level,thread);
235 giacomo 375
    default:
221 giacomo 376
      return -1;
377
  }
378
 
379
  return -1;
380
 
381
}
382
 
339 giacomo 383
int fsf_get_server_level(void)
384
{
385
 
386
  return fsf_server_level;
387
 
388
}
389
 
221 giacomo 390
int fsf_cancel_contract
391
  (fsf_server_id_t *server)
392
{
393
 
394
  int local_scheduler_level, scheduler_id;
395
 
396
  #ifdef FSF_DEBUG
397
    kern_printf("(Remove server %d)",*server);
398
  #endif
399
 
400
  /* Check server id */
401
  if (*server < 0)
402
    return FSF_ERR_INVALID_SERVER;
403
 
241 giacomo 404
  local_scheduler_level = SERVER_get_local_scheduler_level_from_budget(fsf_server_level,*server);
405
  scheduler_id = SERVER_get_local_scheduler_id_from_budget(fsf_server_level,*server);
221 giacomo 406
 
407
  switch (scheduler_id) {
408
    case FSF_SCHEDULER_POSIX:
409
 
410
      /* Check if some thread use the server */
411
      if(POSIXSTAR_budget_has_thread(local_scheduler_level,*server))
412
        return FSF_ERR_SERVER_USED;
413
 
414
      break;
415
    case FSF_SCHEDULER_EDF:
235 giacomo 416
      /* Check if some thread use the server */
417
      if(EDFSTAR_budget_has_thread(local_scheduler_level,*server))
418
        return FSF_ERR_SERVER_USED;
419
      break;
420
 
221 giacomo 421
    case FSF_SCHEDULER_RM:
235 giacomo 422
      /* Check if some thread use the server */
423
      if(RMSTAR_budget_has_thread(local_scheduler_level,*server))
424
        return FSF_ERR_SERVER_USED;
425
 
221 giacomo 426
      break;
334 giacomo 427
 
428
    case FSF_SCHEDULER_MPEG:
429
      /* Check if some thread use the server */
430
      if(MPEGSTAR_budget_has_thread(local_scheduler_level,*server))
431
        return FSF_ERR_SERVER_USED;
432
 
433
      break;
434
 
221 giacomo 435
  }
436
 
241 giacomo 437
  SERVER_removebudget(fsf_server_level,*server);
221 giacomo 438
 
439
  level_free_descriptor(local_scheduler_level);
405 trimarchi 440
 
221 giacomo 441
  remove_contract(*server);
442
 
406 giacomo 443
  recalculate_contract(fsf_max_bw);
405 trimarchi 444
 
221 giacomo 445
  *server = -1;
446
 
447
  return 0;
448
 
449
}
450
 
405 trimarchi 451
int recalculate_contract(bandwidth_t U) {
452
  long int current_bandwidth,temp_U;
453
  int        Qt;
454
  int isok=0;
455
  int i=0;
456
 
407 giacomo 457
  #ifdef FSF_DEBUG
458
    int temp;
459
 
460
    kern_printf("(Recalculate contract)");
461
  #endif
405 trimarchi 462
 
463
  /* The current bandwidth is the min bandwidth */
464
  //current_bandwidth=SERVER_return_bandwidth(fsf_server_level);
465
  #ifdef FSF_DEBUG
410 trimarchi 466
     kern_printf("(nserver %d)", current_server);
405 trimarchi 467
  #endif  
468
 
469
  do  {
470
    current_bandwidth=0;
471
    Qt=0;
410 trimarchi 472
    for (i=0; i<current_server; i++) {
408 trimarchi 473
      if (server_list[i].Qs!=0 && server_list[i].U>server_list[i].Umin)
405 trimarchi 474
         Qt+=server_list[i].Qs;
475
       current_bandwidth+=server_list[i].U;
476
    }
477
 
478
    #ifdef FSF_DEBUG
479
    kern_printf("(Total Quality %d)", Qt);
480
    #endif
481
    isok=1;
410 trimarchi 482
    for (i=0; i<current_server; i++) {
408 trimarchi 483
      if (server_list[i].Qs!=0 && server_list[i].U>server_list[i].Umin) {
405 trimarchi 484
        temp_U=server_list[i].U;
485
        temp_U=temp_U-(current_bandwidth-U)*server_list[i].Qs/Qt;
407 giacomo 486
 
487
        if (temp_U<server_list[i].Umin) {
405 trimarchi 488
           server_list[i].U=server_list[i].Umin;
489
           isok=0;
490
        } else if (temp_U>=server_list[i].Umax)  {
491
           server_list[i].U=server_list[i].Umax;
492
        } else server_list[i].U=temp_U;
493
 
494
#ifdef FSF_DEBUG
495
        mul32div32to32(server_list[i].U,100, MAX_BANDWIDTH, temp);
496
        kern_printf("(Server %d bw %d)", server_list[i].server, temp);
497
#endif 
498
      }
499
    }  
500
 
501
  } while (!isok);
502
 
503
 return 0;
504
}
505
 
506
 
221 giacomo 507
int fsf_renegotiate_contract
508
  (const fsf_contract_parameters_t *new_contract,
509
   fsf_server_id_t server)
510
{
410 trimarchi 511
  SYS_FLAGS f;
512
  TIME T,Q;
513
  int i;
514
 
221 giacomo 515
  #ifdef FSF_DEBUG
516
    kern_printf("(Renegotiate for server %d)",server);
517
  #endif
518
 
519
  if (!new_contract)
520
    return FSF_ERR_NOT_INITIALIZED;
521
 
522
  if (server < 0)
523
    return FSF_ERR_INVALID_SERVER;
405 trimarchi 524
  // compute the new value
525
   f = kern_fsave();
410 trimarchi 526
   // change the parameter
527
   relink_contract_to_server(new_contract, server);
406 giacomo 528
   if (recalculate_contract(fsf_max_bw)==-1)  {
405 trimarchi 529
       kern_frestore(f);
530
       return FSF_ERR_CREATE_SERVER;
531
   }
406 giacomo 532
 
410 trimarchi 533
   for (i=0; i<current_server; i++) {
534
     mul32div32to32(MAX_BANDWIDTH,server_list[i].Cmin,server_list[i].U,T);
535
     #ifdef FSF_DEBUG
536
        kern_printf("(T %ld)", T);
537
     #endif
538
     if (T<=server_list[i].Tmax) {
539
       server_list[i].actual_budget = server_list[i].Cmin;
540
       server_list[i].actual_period = T;
541
       adjust_SERVER_budget(server_list[i].server,server_list[i].Cmin, T);
542
     } else {
543
       mul32div32to32(server_list[i].Tmax,server_list[i].U,MAX_BANDWIDTH,Q);
544
       #ifdef FSF_DEBUG
545
         kern_printf("(Q %ld)", Q);
546
       #endif
547
       server_list[i].actual_budget = Q;
548
       server_list[i].actual_period = server_list[i].Tmax;
549
       adjust_SERVER_budget(server_list[i].server,Q, server_list[i].Tmax);
550
     }
551
     server_list[i].U=server_list[i].Umax;
552
   }
405 trimarchi 553
   kern_frestore(f);
554
   return 0;
221 giacomo 555
}
241 giacomo 556
 
407 giacomo 557
void print_server_list()
558
{
559
 
560
  int i;
561
 
562
  kern_printf("Server List\n");
563
 
410 trimarchi 564
  for(i=0;i<current_server;i++) {
407 giacomo 565
 
566
    kern_printf("[%d] Q:%d T:%d\n",server_list[i].server,(int)server_list[i].actual_budget,(int)server_list[i].actual_period);
567
 
568
  }
569
 
570
}