Subversion Repositories shark

Rev

Rev 408 | Rev 410 | 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
       }
409 trimarchi 214
         server_list[i].U=server_list[i].Umax;
405 trimarchi 215
 
216
    }
217
  }
218
  else  {
219
    kern_frestore(f);
221 giacomo 220
    return FSF_ERR_CREATE_SERVER;
405 trimarchi 221
  }
222
  kern_frestore(f);
223
 
221 giacomo 224
  return 0;
225
 
226
}
227
 
241 giacomo 228
int fsf_create_thread
229
  (fsf_server_id_t    server,
230
   pthread_t         *thread,
231
   pthread_attr_t    *attr,
232
   fsf_thread_code_t  thread_code,
233
   void              *arg,
234
   void              *local_scheduler_arg)
221 giacomo 235
{
236
 
237
  int local_scheduler_level,scheduler_id;
238
 
239
  #ifdef FSF_DEBUG
267 giacomo 240
    kern_printf("(FSF:Insert thread = %d to Server = %d)",*thread,server);
221 giacomo 241
  #endif
242
 
243
  /* Check if server and thread exsist */
241 giacomo 244
  if (server == NIL)
245
    return FSF_ERR_INVALID_SERVER;
221 giacomo 246
 
241 giacomo 247
  local_scheduler_level = SERVER_get_local_scheduler_level_from_budget(fsf_server_level,server);
248
  scheduler_id = SERVER_get_local_scheduler_id_from_budget(fsf_server_level,server);
221 giacomo 249
 
250
  /* Check if thread is already bind */
251
  switch (scheduler_id) {
252
    case FSF_SCHEDULER_POSIX:
253
 
298 giacomo 254
      nrt_task_def_arg(*(NRT_TASK_MODEL *)(local_scheduler_arg),arg);
255
      nrt_task_def_level(*(NRT_TASK_MODEL *)(local_scheduler_arg),local_scheduler_level);
221 giacomo 256
 
298 giacomo 257
      *thread = task_create("POSIXSTAR", thread_code, local_scheduler_arg, NULL);
267 giacomo 258
      if (*thread == NIL) {
259
        #ifdef FSF_DEBUG
260
          kern_printf("(FSF:Error creating thread)");
261
        #endif
241 giacomo 262
        return FSF_ERR_CREATE_THREAD;
267 giacomo 263
      }
221 giacomo 264
 
241 giacomo 265
      POSIXSTAR_setbudget(local_scheduler_level, *thread, (int)(server));
234 giacomo 266
 
221 giacomo 267
    break;
268
    case FSF_SCHEDULER_EDF:
269
 
250 giacomo 270
      hard_task_def_arg(*(HARD_TASK_MODEL *)(local_scheduler_arg),arg);
271
      hard_task_def_level(*(HARD_TASK_MODEL *)(local_scheduler_arg),local_scheduler_level);
272
 
273
      *thread = task_create("EDFSTAR", thread_code, local_scheduler_arg, NULL);
274
      if (*thread == NIL)
275
        return FSF_ERR_CREATE_THREAD;
276
 
277
      EDFSTAR_setbudget(local_scheduler_level, *thread, (int)(server));
278
 
221 giacomo 279
      break;
235 giacomo 280
 
221 giacomo 281
    case FSF_SCHEDULER_RM:
235 giacomo 282
 
273 giacomo 283
      hard_task_def_arg(*(HARD_TASK_MODEL *)(local_scheduler_arg),arg);
284
      hard_task_def_level(*(HARD_TASK_MODEL *)(local_scheduler_arg),local_scheduler_level);
285
 
286
      *thread = task_create("RMSTAR", thread_code, local_scheduler_arg, NULL);
287
      if (*thread == NIL)
288
        return FSF_ERR_CREATE_THREAD;
289
 
290
      RMSTAR_setbudget(local_scheduler_level, *thread, (int)(server));
291
 
292
      break;
334 giacomo 293
    case FSF_SCHEDULER_MPEG:
294
 
295
      hard_task_def_arg(*(HARD_TASK_MODEL *)(local_scheduler_arg),arg);
296
      hard_task_def_level(*(HARD_TASK_MODEL *)(local_scheduler_arg),local_scheduler_level);
297
 
338 giacomo 298
      *thread = task_create("MPEGSTAR", thread_code, local_scheduler_arg, NULL);
334 giacomo 299
      if (*thread == NIL)
300
        return FSF_ERR_CREATE_THREAD;
301
 
302
      MPEGSTAR_setbudget(local_scheduler_level, *thread, (int)(server));
303
 
304
      break;
305
 
221 giacomo 306
    default:
241 giacomo 307
      return FSF_ERR_INVALID_SERVER;
221 giacomo 308
      break;
309
  }
310
 
311
  return 0;
312
 
313
}
314
 
315
int fsf_get_server
316
  (fsf_server_id_t *server,
317
   pthread_t       thread)
318
{
319
  int local_scheduler_level, scheduler_id;
320
 
241 giacomo 321
  local_scheduler_level = SERVER_get_local_scheduler_level_from_pid(fsf_server_level,thread);
322
  scheduler_id = SERVER_get_local_scheduler_id_from_pid(fsf_server_level, thread);
221 giacomo 323
 
324
  switch (scheduler_id) {
325
    case FSF_SCHEDULER_POSIX:
326
      return POSIXSTAR_getbudget(local_scheduler_level,thread);
327
    case FSF_SCHEDULER_EDF:
235 giacomo 328
      return EDFSTAR_getbudget(local_scheduler_level,thread);
221 giacomo 329
    case FSF_SCHEDULER_RM:
235 giacomo 330
      return RMSTAR_getbudget(local_scheduler_level,thread);
334 giacomo 331
    case FSF_SCHEDULER_MPEG:
332
      return MPEGSTAR_getbudget(local_scheduler_level,thread);
235 giacomo 333
    default:
221 giacomo 334
      return -1;
335
  }
336
 
337
  return -1;
338
 
339
}
340
 
339 giacomo 341
int fsf_get_server_level(void)
342
{
343
 
344
  return fsf_server_level;
345
 
346
}
347
 
221 giacomo 348
int fsf_cancel_contract
349
  (fsf_server_id_t *server)
350
{
351
 
352
  int local_scheduler_level, scheduler_id;
353
 
354
  #ifdef FSF_DEBUG
355
    kern_printf("(Remove server %d)",*server);
356
  #endif
357
 
358
  /* Check server id */
359
  if (*server < 0)
360
    return FSF_ERR_INVALID_SERVER;
361
 
241 giacomo 362
  local_scheduler_level = SERVER_get_local_scheduler_level_from_budget(fsf_server_level,*server);
363
  scheduler_id = SERVER_get_local_scheduler_id_from_budget(fsf_server_level,*server);
221 giacomo 364
 
365
  switch (scheduler_id) {
366
    case FSF_SCHEDULER_POSIX:
367
 
368
      /* Check if some thread use the server */
369
      if(POSIXSTAR_budget_has_thread(local_scheduler_level,*server))
370
        return FSF_ERR_SERVER_USED;
371
 
372
      break;
373
    case FSF_SCHEDULER_EDF:
235 giacomo 374
      /* Check if some thread use the server */
375
      if(EDFSTAR_budget_has_thread(local_scheduler_level,*server))
376
        return FSF_ERR_SERVER_USED;
377
      break;
378
 
221 giacomo 379
    case FSF_SCHEDULER_RM:
235 giacomo 380
      /* Check if some thread use the server */
381
      if(RMSTAR_budget_has_thread(local_scheduler_level,*server))
382
        return FSF_ERR_SERVER_USED;
383
 
221 giacomo 384
      break;
334 giacomo 385
 
386
    case FSF_SCHEDULER_MPEG:
387
      /* Check if some thread use the server */
388
      if(MPEGSTAR_budget_has_thread(local_scheduler_level,*server))
389
        return FSF_ERR_SERVER_USED;
390
 
391
      break;
392
 
221 giacomo 393
  }
394
 
241 giacomo 395
  SERVER_removebudget(fsf_server_level,*server);
221 giacomo 396
 
397
  level_free_descriptor(local_scheduler_level);
405 trimarchi 398
 
221 giacomo 399
  remove_contract(*server);
400
 
406 giacomo 401
  recalculate_contract(fsf_max_bw);
405 trimarchi 402
 
221 giacomo 403
  *server = -1;
404
 
405
  return 0;
406
 
407
}
408
 
405 trimarchi 409
int recalculate_contract(bandwidth_t U) {
410
  long int current_bandwidth,temp_U;
411
  int        Qt;
412
  int isok=0;
413
  int i=0;
414
 
407 giacomo 415
  #ifdef FSF_DEBUG
416
    int temp;
417
 
418
    kern_printf("(Recalculate contract)");
419
  #endif
405 trimarchi 420
 
421
  /* The current bandwidth is the min bandwidth */
422
  //current_bandwidth=SERVER_return_bandwidth(fsf_server_level);
423
  #ifdef FSF_DEBUG
424
     kern_printf("(nserver %d)", current);
425
  #endif
426
 
427
  do  {
428
    current_bandwidth=0;
429
    Qt=0;
430
    for (i=0; i<current; i++) {
408 trimarchi 431
      if (server_list[i].Qs!=0 && server_list[i].U>server_list[i].Umin)
405 trimarchi 432
         Qt+=server_list[i].Qs;
433
       current_bandwidth+=server_list[i].U;
434
    }
435
 
436
    #ifdef FSF_DEBUG
437
    kern_printf("(Total Quality %d)", Qt);
438
    #endif
439
    isok=1;
440
    for (i=0; i<current; i++) {
408 trimarchi 441
      if (server_list[i].Qs!=0 && server_list[i].U>server_list[i].Umin) {
405 trimarchi 442
        temp_U=server_list[i].U;
443
	temp_U=temp_U-(current_bandwidth-U)*server_list[i].Qs/Qt;
407 giacomo 444
 
445
        if (temp_U<server_list[i].Umin) {
405 trimarchi 446
	   server_list[i].U=server_list[i].Umin;
447
	   isok=0;
448
	} else if (temp_U>=server_list[i].Umax)  {
449
	   server_list[i].U=server_list[i].Umax;
450
	} else server_list[i].U=temp_U;
451
 
452
#ifdef FSF_DEBUG
453
	mul32div32to32(server_list[i].U,100, MAX_BANDWIDTH, temp);
454
        kern_printf("(Server %d bw %d)", server_list[i].server, temp);
455
#endif
456
      }
457
    }
458
 
459
  } while (!isok);
460
 
461
 return 0;
462
}
463
 
464
 
221 giacomo 465
int fsf_renegotiate_contract
466
  (const fsf_contract_parameters_t *new_contract,
467
   fsf_server_id_t server)
468
{
405 trimarchi 469
  SYS_FLAGS f;
221 giacomo 470
  #ifdef FSF_DEBUG
471
    kern_printf("(Renegotiate for server %d)",server);
472
  #endif
473
 
474
  if (!new_contract)
475
    return FSF_ERR_NOT_INITIALIZED;
476
 
477
  if (server < 0)
478
    return FSF_ERR_INVALID_SERVER;
405 trimarchi 479
  // compute the new value
480
  //
481
   f = kern_fsave();
406 giacomo 482
   if (recalculate_contract(fsf_max_bw)==-1)  {
405 trimarchi 483
       kern_frestore(f);
484
       return FSF_ERR_CREATE_SERVER;
485
   }
406 giacomo 486
 
405 trimarchi 487
   kern_frestore(f);
488
   return 0;
221 giacomo 489
}
241 giacomo 490
 
407 giacomo 491
void print_server_list()
492
{
493
 
494
  int i;
495
 
496
  kern_printf("Server List\n");
497
 
498
  for(i=0;i<current;i++) {
499
 
500
    kern_printf("[%d] Q:%d T:%d\n",server_list[i].server,(int)server_list[i].actual_budget,(int)server_list[i].actual_period);
501
 
502
  }
503
 
504
}