Subversion Repositories shark

Rev

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