Subversion Repositories shark

Rev

Rev 406 | Rev 408 | 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
 
405 trimarchi 24
int current=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");
405 trimarchi 33
  current=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
 
96
int link_contract_to_server(const fsf_contract_parameters_t *contract,
97
                            fsf_server_id_t server)
98
{
405 trimarchi 99
  TIME T,Q;
407 giacomo 100
#ifdef FSF_DEBUG
405 trimarchi 101
  int temp;
407 giacomo 102
 
405 trimarchi 103
  kern_printf("(Link Server %d)",server);
104
#endif
105
 
106
  server_list[current].server=server;
107
  server_list[current].Qs=1;
108
 
109
  T=TIMESPEC2USEC(&contract->period_min);
110
  Q=TIMESPEC2USEC(&contract->budget_max);
111
  mul32div32to32(MAX_BANDWIDTH,Q,T,server_list[current].Umax);
112
 
113
  T=TIMESPEC2USEC(&contract->period_max);
114
  server_list[current].Tmax=T;
115
 
116
  Q=TIMESPEC2USEC(&contract->budget_min);
117
  server_list[current].Cmin=Q;
118
 
119
  mul32div32to32(MAX_BANDWIDTH,Q,T,server_list[current].Umin);
120
  server_list[current].U=server_list[current].Umax;
221 giacomo 121
 
405 trimarchi 122
#ifdef FSF_DEBUG
123
  mul32div32to32(server_list[current].Umax,100, MAX_BANDWIDTH, temp);
124
  kern_printf("(Umax %d)",temp);
125
  mul32div32to32(server_list[current].Umin,100, MAX_BANDWIDTH, temp);
126
  kern_printf("(Umin %d)",temp);
127
#endif
128
 
129
 
130
  current++;
221 giacomo 131
  return 0;
132
 
133
}
134
 
135
int remove_contract(fsf_server_id_t server)
136
{
405 trimarchi 137
  int i=0;
138
  // find the contract
139
  while(i<current) {
140
     if (server_list[i].server==server) break;
141
     i++;
142
  }
221 giacomo 143
 
405 trimarchi 144
  // compress the array;
145
  while (i<(current-1)) {
146
     server_list[i].server=server_list[i+1].server;
147
     server_list[i].Umin=server_list[i+1].Umin;
406 giacomo 148
     server_list[i].U=server_list[i+1].Umax;    
405 trimarchi 149
     server_list[i].Umax=server_list[i+1].Umax;
150
     server_list[i].Cmin=server_list[i+1].Cmin;
151
     server_list[i].Tmax=server_list[i+1].Tmax;
152
     server_list[i].Qs=server_list[i+1].Qs;
153
     i++;
154
  }
155
  current--;
156
 
157
 
221 giacomo 158
  return 0;
159
 
160
}
161
 
162
 
163
int fsf_negotiate_contract
164
  (const fsf_contract_parameters_t *contract,
165
   fsf_server_id_t                 *server)
166
{
405 trimarchi 167
  SYS_FLAGS f;
168
  int i=0;
169
  TIME T;
170
  TIME Q;
221 giacomo 171
  /* Check if contract is initialized */
172
  if (!contract) return FSF_ERR_NOT_INITIALIZED;
173
 
174
  /* Admission Test */
175
  if (FSF_ADMISSION_TEST_IS_ENABLED)
176
    if (add_contract(contract))
177
      return FSF_ERR_CONTRACT_REJECTED;
405 trimarchi 178
  f = kern_fsave();
221 giacomo 179
 
241 giacomo 180
  /* SERVER => BUDGET */    
181
  set_SERVER_budget_from_contract(contract,server);
221 giacomo 182
 
183
  #ifdef FSF_DEBUG
184
    kern_printf("(New Server %d)",*server);
185
  #endif
186
 
405 trimarchi 187
  if (*server >= 0) {
221 giacomo 188
    link_contract_to_server(contract,*server);
406 giacomo 189
    if (recalculate_contract(fsf_max_bw)==-1)  {
405 trimarchi 190
       kern_frestore(f);
191
       return FSF_ERR_CREATE_SERVER;
192
    }
193
#ifdef  FSF_DEBUG
194
    kern_printf("(Adjust budget)");
195
#endif    
196
    for (i=0; i<current; i++) {
197
       mul32div32to32(MAX_BANDWIDTH,server_list[i].Cmin,server_list[i].U,T);
198
       #ifdef FSF_DEBUG
199
       kern_printf("(T %ld)", T);
200
       #endif
407 giacomo 201
       if (T<=server_list[i].Tmax) {
202
          server_list[i].actual_budget = server_list[i].Cmin;
203
          server_list[i].actual_period = T;
405 trimarchi 204
          adjust_SERVER_budget(server_list[i].server,server_list[i].Cmin, T);
407 giacomo 205
       } else {
405 trimarchi 206
         mul32div32to32(server_list[i].Tmax,server_list[i].U,MAX_BANDWIDTH,Q);
207
         #ifdef FSF_DEBUG
208
         kern_printf("(Q %ld)", Q);
209
         #endif
407 giacomo 210
         server_list[i].actual_budget = Q;
211
         server_list[i].actual_period = server_list[i].Tmax;
405 trimarchi 212
         adjust_SERVER_budget(server_list[i].server,Q, server_list[i].Tmax);
213
       }
214
 
215
    }
216
  }
217
  else  {
218
    kern_frestore(f);
221 giacomo 219
    return FSF_ERR_CREATE_SERVER;
405 trimarchi 220
  }
221
  kern_frestore(f);
222
 
221 giacomo 223
  return 0;
224
 
225
}
226
 
241 giacomo 227
int fsf_create_thread
228
  (fsf_server_id_t    server,
229
   pthread_t         *thread,
230
   pthread_attr_t    *attr,
231
   fsf_thread_code_t  thread_code,
232
   void              *arg,
233
   void              *local_scheduler_arg)
221 giacomo 234
{
235
 
236
  int local_scheduler_level,scheduler_id;
237
 
238
  #ifdef FSF_DEBUG 
267 giacomo 239
    kern_printf("(FSF:Insert thread = %d to Server = %d)",*thread,server);
221 giacomo 240
  #endif
241
 
242
  /* Check if server and thread exsist */
241 giacomo 243
  if (server == NIL)
244
    return FSF_ERR_INVALID_SERVER;
221 giacomo 245
 
241 giacomo 246
  local_scheduler_level = SERVER_get_local_scheduler_level_from_budget(fsf_server_level,server);
247
  scheduler_id = SERVER_get_local_scheduler_id_from_budget(fsf_server_level,server);
221 giacomo 248
 
249
  /* Check if thread is already bind */
250
  switch (scheduler_id) {
251
    case FSF_SCHEDULER_POSIX:
252
 
298 giacomo 253
      nrt_task_def_arg(*(NRT_TASK_MODEL *)(local_scheduler_arg),arg);
254
      nrt_task_def_level(*(NRT_TASK_MODEL *)(local_scheduler_arg),local_scheduler_level);
221 giacomo 255
 
298 giacomo 256
      *thread = task_create("POSIXSTAR", thread_code, local_scheduler_arg, NULL);
267 giacomo 257
      if (*thread == NIL) {
258
        #ifdef FSF_DEBUG
259
          kern_printf("(FSF:Error creating thread)");
260
        #endif
241 giacomo 261
        return FSF_ERR_CREATE_THREAD;
267 giacomo 262
      }
221 giacomo 263
 
241 giacomo 264
      POSIXSTAR_setbudget(local_scheduler_level, *thread, (int)(server));
234 giacomo 265
 
221 giacomo 266
    break;
267
    case FSF_SCHEDULER_EDF:
268
 
250 giacomo 269
      hard_task_def_arg(*(HARD_TASK_MODEL *)(local_scheduler_arg),arg);
270
      hard_task_def_level(*(HARD_TASK_MODEL *)(local_scheduler_arg),local_scheduler_level);
271
 
272
      *thread = task_create("EDFSTAR", thread_code, local_scheduler_arg, NULL);
273
      if (*thread == NIL)
274
        return FSF_ERR_CREATE_THREAD;
275
 
276
      EDFSTAR_setbudget(local_scheduler_level, *thread, (int)(server));
277
 
221 giacomo 278
      break;
235 giacomo 279
 
221 giacomo 280
    case FSF_SCHEDULER_RM:
235 giacomo 281
 
273 giacomo 282
      hard_task_def_arg(*(HARD_TASK_MODEL *)(local_scheduler_arg),arg);
283
      hard_task_def_level(*(HARD_TASK_MODEL *)(local_scheduler_arg),local_scheduler_level);
284
 
285
      *thread = task_create("RMSTAR", thread_code, local_scheduler_arg, NULL);
286
      if (*thread == NIL)
287
        return FSF_ERR_CREATE_THREAD;
288
 
289
      RMSTAR_setbudget(local_scheduler_level, *thread, (int)(server));
290
 
291
      break;
334 giacomo 292
    case FSF_SCHEDULER_MPEG:
293
 
294
      hard_task_def_arg(*(HARD_TASK_MODEL *)(local_scheduler_arg),arg);
295
      hard_task_def_level(*(HARD_TASK_MODEL *)(local_scheduler_arg),local_scheduler_level);
296
 
338 giacomo 297
      *thread = task_create("MPEGSTAR", thread_code, local_scheduler_arg, NULL);
334 giacomo 298
      if (*thread == NIL)
299
        return FSF_ERR_CREATE_THREAD;
300
 
301
      MPEGSTAR_setbudget(local_scheduler_level, *thread, (int)(server));
302
 
303
      break;
304
 
221 giacomo 305
    default:
241 giacomo 306
      return FSF_ERR_INVALID_SERVER;
221 giacomo 307
      break;
308
  }
309
 
310
  return 0;
311
 
312
}
313
 
314
int fsf_get_server
315
  (fsf_server_id_t *server,
316
   pthread_t       thread)
317
{
318
  int local_scheduler_level, scheduler_id;
319
 
241 giacomo 320
  local_scheduler_level = SERVER_get_local_scheduler_level_from_pid(fsf_server_level,thread);
321
  scheduler_id = SERVER_get_local_scheduler_id_from_pid(fsf_server_level, thread);
221 giacomo 322
 
323
  switch (scheduler_id) {
324
    case FSF_SCHEDULER_POSIX:  
325
      return POSIXSTAR_getbudget(local_scheduler_level,thread);
326
    case FSF_SCHEDULER_EDF:
235 giacomo 327
      return EDFSTAR_getbudget(local_scheduler_level,thread);
221 giacomo 328
    case FSF_SCHEDULER_RM:
235 giacomo 329
      return RMSTAR_getbudget(local_scheduler_level,thread);
334 giacomo 330
    case FSF_SCHEDULER_MPEG:
331
      return MPEGSTAR_getbudget(local_scheduler_level,thread);
235 giacomo 332
    default:
221 giacomo 333
      return -1;
334
  }
335
 
336
  return -1;
337
 
338
}
339
 
339 giacomo 340
int fsf_get_server_level(void)
341
{
342
 
343
  return fsf_server_level;
344
 
345
}
346
 
221 giacomo 347
int fsf_cancel_contract
348
  (fsf_server_id_t *server)
349
{
350
 
351
  int local_scheduler_level, scheduler_id;
352
 
353
  #ifdef FSF_DEBUG
354
    kern_printf("(Remove server %d)",*server);
355
  #endif
356
 
357
  /* Check server id */
358
  if (*server < 0)
359
    return FSF_ERR_INVALID_SERVER;
360
 
241 giacomo 361
  local_scheduler_level = SERVER_get_local_scheduler_level_from_budget(fsf_server_level,*server);
362
  scheduler_id = SERVER_get_local_scheduler_id_from_budget(fsf_server_level,*server);
221 giacomo 363
 
364
  switch (scheduler_id) {
365
    case FSF_SCHEDULER_POSIX:
366
 
367
      /* Check if some thread use the server */
368
      if(POSIXSTAR_budget_has_thread(local_scheduler_level,*server))
369
        return FSF_ERR_SERVER_USED;
370
 
371
      break;
372
    case FSF_SCHEDULER_EDF:
235 giacomo 373
      /* Check if some thread use the server */
374
      if(EDFSTAR_budget_has_thread(local_scheduler_level,*server))
375
        return FSF_ERR_SERVER_USED;
376
      break;
377
 
221 giacomo 378
    case FSF_SCHEDULER_RM:
235 giacomo 379
      /* Check if some thread use the server */
380
      if(RMSTAR_budget_has_thread(local_scheduler_level,*server))
381
        return FSF_ERR_SERVER_USED;
382
 
221 giacomo 383
      break;
334 giacomo 384
 
385
    case FSF_SCHEDULER_MPEG:
386
      /* Check if some thread use the server */
387
      if(MPEGSTAR_budget_has_thread(local_scheduler_level,*server))
388
        return FSF_ERR_SERVER_USED;
389
 
390
      break;
391
 
221 giacomo 392
  }
393
 
241 giacomo 394
  SERVER_removebudget(fsf_server_level,*server);
221 giacomo 395
 
396
  level_free_descriptor(local_scheduler_level);
405 trimarchi 397
 
221 giacomo 398
  remove_contract(*server);
399
 
406 giacomo 400
  recalculate_contract(fsf_max_bw);
405 trimarchi 401
 
221 giacomo 402
  *server = -1;
403
 
404
  return 0;
405
 
406
}
407
 
405 trimarchi 408
int recalculate_contract(bandwidth_t U) {
409
  long int current_bandwidth,temp_U;
410
  int        Qt;
411
  int isok=0;
412
  int i=0;
413
 
407 giacomo 414
  #ifdef FSF_DEBUG
415
    int temp;
416
 
417
    kern_printf("(Recalculate contract)");
418
  #endif
405 trimarchi 419
 
420
  /* The current bandwidth is the min bandwidth */
421
  //current_bandwidth=SERVER_return_bandwidth(fsf_server_level);
422
  #ifdef FSF_DEBUG
423
     kern_printf("(nserver %d)", current);
424
  #endif  
425
 
426
  do  {
427
    current_bandwidth=0;
428
    Qt=0;
429
    for (i=0; i<current; i++) {
407 giacomo 430
      if (server_list[i].Qs!=0)
405 trimarchi 431
         Qt+=server_list[i].Qs;
432
       current_bandwidth+=server_list[i].U;
433
    }
434
 
435
    #ifdef FSF_DEBUG
436
    kern_printf("(Total Quality %d)", Qt);
437
    #endif
438
    isok=1;
439
    for (i=0; i<current; i++) {
407 giacomo 440
      if (server_list[i].Qs!=0) {
405 trimarchi 441
        temp_U=server_list[i].U;
442
        temp_U=temp_U-(current_bandwidth-U)*server_list[i].Qs/Qt;
407 giacomo 443
 
444
        if (temp_U<server_list[i].Umin) {
405 trimarchi 445
           server_list[i].U=server_list[i].Umin;
446
           isok=0;
447
        } else if (temp_U>=server_list[i].Umax)  {
448
           server_list[i].U=server_list[i].Umax;
449
        } else server_list[i].U=temp_U;
450
 
451
#ifdef FSF_DEBUG
452
        mul32div32to32(server_list[i].U,100, MAX_BANDWIDTH, temp);
453
        kern_printf("(Server %d bw %d)", server_list[i].server, temp);
454
#endif 
455
      }
456
    }  
457
 
458
  } while (!isok);
459
 
460
 return 0;
461
}
462
 
463
 
221 giacomo 464
int fsf_renegotiate_contract
465
  (const fsf_contract_parameters_t *new_contract,
466
   fsf_server_id_t server)
467
{
405 trimarchi 468
  SYS_FLAGS f;
221 giacomo 469
  #ifdef FSF_DEBUG
470
    kern_printf("(Renegotiate for server %d)",server);
471
  #endif
472
 
473
  if (!new_contract)
474
    return FSF_ERR_NOT_INITIALIZED;
475
 
476
  if (server < 0)
477
    return FSF_ERR_INVALID_SERVER;
405 trimarchi 478
  // compute the new value
479
  //
480
   f = kern_fsave();
406 giacomo 481
   if (recalculate_contract(fsf_max_bw)==-1)  {
405 trimarchi 482
       kern_frestore(f);
483
       return FSF_ERR_CREATE_SERVER;
484
   }
406 giacomo 485
 
405 trimarchi 486
   kern_frestore(f);
487
   return 0;
221 giacomo 488
}
241 giacomo 489
 
407 giacomo 490
void print_server_list()
491
{
492
 
493
  int i;
494
 
495
  kern_printf("Server List\n");
496
 
497
  for(i=0;i<current;i++) {
498
 
499
    kern_printf("[%d] Q:%d T:%d\n",server_list[i].server,(int)server_list[i].actual_budget,(int)server_list[i].actual_period);
500
 
501
  }
502
 
503
}