Subversion Repositories shark

Rev

Rev 38 | Rev 920 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 pj 1
/*
2
 * Project: S.Ha.R.K.
3
 *
4
 * Coordinators:
5
 *   Giorgio Buttazzo    <giorgio@sssup.it>
6
 *   Paolo Gai           <pj@gandalf.sssup.it>
7
 *
8
 * Authors     :
9
 *   Paolo Gai           <pj@gandalf.sssup.it>
10
 *   (see the web pages for full authors list)
11
 *
12
 * ReTiS Lab (Scuola Superiore S.Anna - Pisa - Italy)
13
 *
14
 * http://www.sssup.it
15
 * http://retis.sssup.it
16
 * http://shark.sssup.it
17
 */
18
 
19
/**
20
 ------------
122 giacomo 21
 CVS :        $Id: init.c,v 1.3 2003-04-16 17:18:15 giacomo Exp $
2 pj 22
 
23
 File:        $File$
122 giacomo 24
 Revision:    $Revision: 1.3 $
25
 Last update: $Date: 2003-04-16 17:18:15 $
2 pj 26
 ------------
27
 
38 pj 28
 - Kernel module registration functions
29
 - miscellaneous functions related to module registration, system init and end
2 pj 30
 
31
**/
32
 
33
/*
34
 * Copyright (C) 2000 Paolo Gai
35
 *
36
 * This program is free software; you can redistribute it and/or modify
37
 * it under the terms of the GNU General Public License as published by
38
 * the Free Software Foundation; either version 2 of the License, or
39
 * (at your option) any later version.
40
 *
41
 * This program is distributed in the hope that it will be useful,
42
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
43
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
44
 * GNU General Public License for more details.
45
 *
46
 * You should have received a copy of the GNU General Public License
47
 * along with this program; if not, write to the Free Software
48
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
49
 *
50
 */
51
 
52
#include <stdarg.h>
53
#include <ll/ll.h>
54
#include <ll/stdlib.h>
55
#include <ll/stdio.h>
56
#include <ll/string.h>
57
#include <kernel/config.h>
58
#include <kernel/model.h>
59
#include <kernel/const.h>
60
#include <sys/types.h>
61
#include <kernel/types.h>
62
#include <kernel/descr.h>
63
#include <errno.h>
64
#include <kernel/var.h>
65
#include <kernel/func.h>
66
 
38 pj 67
/***********************************************************************
68
 * Runlevel management
69
 ***********************************************************************/
70
 
2 pj 71
/*+ List of function to call at each rnlevel;
72
    they are posted with sys_atrunlevel +*/
73
static struct exit_func {
74
    void (*f)(void *);
75
    void *arg;
76
    int no_at_abort;
77
    int next;
78
} runlevel_list[MAX_RUNLEVEL_FUNC];
79
 
80
static int runlevel_init_list;
81
static int runlevel_init_tail;
82
static int runlevel_shutdown_list;
83
static int runlevel_before_list;
84
static int runlevel_after_list;
85
static int runlevel_free;
86
 
87
 
88
void runlevel_init()
89
{
90
  int i;
91
 
92
  for (i = 0; i < MAX_RUNLEVEL_FUNC-1; i++)
93
    runlevel_list[i].next = i+1;
94
  runlevel_list[MAX_RUNLEVEL_FUNC-1].next = -1;
95
 
96
  runlevel_init_list     = -1;
97
  runlevel_init_tail     = -1;
98
  runlevel_shutdown_list = -1;
99
  runlevel_before_list   = -1;
100
  runlevel_after_list    = -1;
101
  runlevel_free          = 0;
102
}
103
 
104
/*+ flags may be RUNLEVEL_XXX...
105
    aborting may be 0 or NO_AT_ABORT +*/
106
void call_runlevel_func(int runlevel, int aborting)
107
{
108
  int i, j;
109
 
110
  switch (runlevel) {
111
    case RUNLEVEL_INIT:
112
      i = runlevel_init_list;
113
      runlevel_init_list = -1;
114
      break;
115
    case RUNLEVEL_SHUTDOWN:
116
      i = runlevel_shutdown_list;
117
      runlevel_shutdown_list = -1;
118
      break;
119
    case RUNLEVEL_BEFORE_EXIT:
120
      i = runlevel_before_list;
121
      runlevel_before_list = -1;
122
      break;
123
    case RUNLEVEL_AFTER_EXIT:
124
      i = runlevel_after_list;
125
      runlevel_after_list = -1;
126
      break;
127
    default:
128
      return;
129
  }
130
 
131
  // the task_activate must differ!!! look at activate.c
132
  calling_runlevel_func = 1;
133
 
134
  while (i != -1) {
135
    if (!(aborting && runlevel_list[i].no_at_abort))
136
      runlevel_list[i].f(runlevel_list[i].arg);
137
 
138
    j = i;
139
    i = runlevel_list[i].next;
140
 
141
    runlevel_list[j].next = runlevel_free;
142
    runlevel_free = j;
143
  }
144
 
145
  calling_runlevel_func = 0;
146
 
147
}
148
 
149
/*+ Use this function to post your own runlevel operations
150
    (when uses some defines contained in const.h) +*/
151
int sys_atrunlevel(void (*func_code)(void *),void *parm, BYTE when)
152
{
153
    register int i = 0;
154
    SYS_FLAGS f;
155
 
156
    f = kern_fsave();
157
    if (runlevel_free == -1) {
158
        errno = ETOOMUCH_EXITFUNC;
159
        kern_frestore(f);
160
        return -1;
161
    }
162
 
163
    i = runlevel_free;
164
    runlevel_free = runlevel_list[runlevel_free].next;
165
 
166
    runlevel_list[i].f = func_code;
167
    runlevel_list[i].arg = parm;
168
    runlevel_list[i].no_at_abort = when & NO_AT_ABORT;
169
 
122 giacomo 170
    switch (when & RUNLEVEL_MASK) {
2 pj 171
      case RUNLEVEL_INIT:
172
        /* the init functions are called in the order they are posted
173
           so, we insert at the queue tail */
174
        runlevel_list[i].next = -1;
175
        if (runlevel_init_list == -1)
176
          runlevel_init_list = i;
177
        else
178
          runlevel_list[runlevel_init_tail].next = i;
179
        runlevel_init_tail = i;
180
        break;
181
      case RUNLEVEL_SHUTDOWN:
182
        runlevel_list[i].next = runlevel_shutdown_list;
183
        runlevel_shutdown_list = i;
184
        break;
185
      case RUNLEVEL_BEFORE_EXIT:
186
        runlevel_list[i].next = runlevel_before_list;
187
        runlevel_before_list = i;
188
        break;
189
      default: // RUNLEVEL_AFTER_EXIT
190
        runlevel_list[i].next = runlevel_after_list;
191
        runlevel_after_list = i;
192
    }
193
 
194
    kern_frestore(f);
195
    return 0;
196
}
197
 
38 pj 198
/***********************************************************************
199
 * Level Default Descriptor
200
 ***********************************************************************/
2 pj 201
 
38 pj 202
static void level_excfunc(LEVEL l)
203
{
204
  printk(KERN_EMERG "unreg scheduling function called, level=%d!\n", l);
205
  kern_raise(XINVALID_TASK, exec_shadow);
206
}
207
 
208
static int level_return1(void) { return 1; }
209
static int level_returnminus1(void) { return -1; }
210
static void level_nothing(void) { }
211
static int level_return0(void) { return 0; }
212
 
213
static level_des level_default_descriptor =
214
{
215
  (void (*)(LEVEL,PID,TASK_MODEL *))level_excfunc, /* private_insert   */
216
  (void (*)(LEVEL,PID))             level_excfunc, /* private_extract  */
217
  (int  (*)(LEVEL,PID))             level_return0, /* private_eligible */
218
  (void (*)(LEVEL,PID, int))        level_excfunc, /* private_dispatch */
219
  (void (*)(LEVEL,PID))             level_excfunc, /* private_epilogue */
220
 
221
  (PID  (*)(LEVEL))                 level_returnminus1, /* pubvlic_scheduler */
222
  (int  (*)(LEVEL,bandwidth_t *))   level_return1, /* public_guarantee */
223
  (int  (*)(LEVEL,PID,TASK_MODEL *))level_returnminus1, /* public_create */
224
  (void (*)(LEVEL,PID))             level_nothing, /* public_detach */
225
  (void (*)(LEVEL,PID))             level_excfunc, /* public_end       */
226
  (int  (*)(LEVEL,PID))             level_return0, /* public_eligible */
227
  (void (*)(LEVEL,PID, int))        level_excfunc, /* public_dispatch  */
228
  (void (*)(LEVEL,PID))             level_excfunc, /* public_epilogue  */
229
  (void (*)(LEVEL,PID))             level_excfunc, /* public_activate  */
230
  (void (*)(LEVEL,PID))             level_excfunc, /* public_unblock   */
231
  (void (*)(LEVEL,PID))             level_excfunc, /* public_block     */
232
  (int  (*)(LEVEL,PID,void *))      level_excfunc, /* public_message   */
233
};
234
 
235
 
236
/***********************************************************************
237
 * Module registration
238
 ***********************************************************************/
239
 
240
/* this function initializes all the data structures used by the level
241
   registration functions */
242
void levels_init(void)
243
{
244
  int l;
245
  for (l=0; l<MAX_SCHED_LEVEL; l++) {
246
    level_table[l] = &level_default_descriptor;
247
    level_used[l] = 0;
248
    level_next[l] = l+1;
249
    level_prev[l] = l-1;
250
  }
251
 
252
  level_next[MAX_SCHED_LEVEL-1l] = -1;
253
  level_prev[0] = -1;
254
 
255
  level_first = -1;
256
  level_last = -1;
257
  level_free = 0;
258
}
259
 
2 pj 260
/*+ This function returns a level_des **. the value returned shall be
38 pj 261
    used to register a level module.
262
 
263
    The function is usually called at module registration time.  The
264
    function can also be called when the system is already started, to
265
    allow the implementation of dynamic module registration.  
266
 
267
    The argument must be the size of the data block that have to be allocated
268
 
269
    The function returns the number of the descriptor allocated for the module
270
    or -1 in case there are no free descriptors.
271
 
272
    The function also reserves a descriptor with size s, initialized
273
    with default function pointers.
274
 
275
+*/
276
LEVEL level_alloc_descriptor(size_t s)
2 pj 277
{
38 pj 278
  LEVEL l;
279
  /* try to find a free descriptor */
280
  if (level_free == -1)
281
    return -1;
282
 
283
  /* alloc it */
284
  l = level_free;
285
  level_free = level_next[l];
286
 
287
  level_used[l] = 1;
288
 
289
  /* insert the module as the last in the scheduling module's list */
290
  if (level_last == -1) {
291
    level_first = l;
292
    level_prev[l] = -1;
2 pj 293
  }
38 pj 294
  else {
295
    level_next[level_last] = l;
296
    level_prev[l] = level_last;
297
  }
298
  level_last = l;
299
  level_next[l] = -1;
2 pj 300
 
38 pj 301
  /* allocate the descriptor! */
302
  if (s < sizeof(level_des))
303
    s = sizeof(level_des);
304
 
305
  level_table[l] = (level_des *)kern_alloc(s);
306
 
307
  *(level_table[l]) = level_default_descriptor;
308
 
309
  level_size[l] = s;
310
 
311
  /* return the descriptor index */
312
  return l;
2 pj 313
}
314
 
315
 
38 pj 316
/*+ This function release a level descriptor previously allocated using
317
  level_alloc_descriptor().
318
 
319
  The function returns 0 if the level has been freed, or -1 if someone is
320
  using it, -2 if the level has never been registered.
321
 
322
+*/
323
int level_free_descriptor(LEVEL l)
324
{
325
  if (level_used[l] == 0)
326
    return -2;
327
  else if (level_used[l] > 1)
328
    return -1;
329
 
330
  /* we can free the descriptor */
331
  level_used[l] = 0;
332
 
333
  /* remove it from the "first" queue */
334
  if (level_prev[l] == -1)
335
    level_first = level_next[l];
336
  else
337
    level_next[level_prev[l]] = level_next[l];
338
 
339
  if (level_next[l] == -1)
340
    level_last = level_prev[l];
341
  else
342
    level_prev[level_next[l]] = level_prev[l];
343
 
344
  /* ... and put it in the free queue */
345
  level_prev[level_free] = l;
346
  level_next[l] = level_free;
347
  level_free = l;
348
 
349
  /* finally, free the memory allocated to it */
350
  kern_free(level_table[l], level_size[l]);
351
 
352
  return 0;
353
}
354
 
355
/* Call this if you want to say that your module is using module l
356
   (e.g., for calling its private functions) */
357
int level_use_descriptor(LEVEL l)
358
{
359
  return ++level_used[l];
360
}
361
 
362
/* Call this when you no more need the module l */
363
int level_unuse_descriptor(LEVEL l)
364
{
365
  return --level_used[l];
366
}
367
 
368
 
2 pj 369
/*+ This function returns a resource_des **. the value returned shall be
370
    used to register a resource module. The function shall be called only at
371
    module registration time. It assume that the system is not yet
372
    initialized, so we shall not call sys_abort...                     +*/
373
RLEVEL resource_alloc_descriptor()
374
{
375
  if (res_levels == MAX_RES_LEVEL)
376
  {
377
    printk("Too many resource levels!!!\n");
38 pj 378
    sys_end();
2 pj 379
  }
380
 
381
  return res_levels++;
382
}
383
 
38 pj 384
 
385
/***********************************************************************
386
 * Parameter parsing (argc, argv)
387
 ***********************************************************************/
388
 
2 pj 389
/*+ This function compute the command line parameters from the multiboot_info
390
    NOTE: this function modify the multiboot struct, so this function and
391
    __call_main__ are mutually exclusives!!! +*/
392
void __compute_args__(struct multiboot_info *mbi, int *_argc, char **_argv)
393
{
394
  register int i = 0;
395
  char *cmdline = (char *)(mbi->cmdline);
396
 
397
  /* creates the command line... */
398
  *_argc = 0;
399
  if (mbi->flags & MB_INFO_CMDLINE) {
400
    while (cmdline[i] != 0) {
401
      _argv[*_argc] = &(cmdline[i]);
402
      while (cmdline[i] != ' ' && cmdline[i] != 0) i++;
403
      if (cmdline[i] == ' ') {
404
        cmdline[i] = 0; i++; (*_argc)++;
405
      }
406
    }
407
    (*_argc)++;
408
  }
409
}
410
 
411
/* note that the prototype is not public... so the user can
412
    also use a int main(void), void main(void)... and so on... */
413
int main(int argc, char **argv);
414
 
415
/*+ This function calls the standard C main() function, with a
416
    parameter list up to 100 parameters                        +*/
417
int __call_main__(struct multiboot_info *mbi)
418
{
419
  int _argc;
420
  char *_argv[100];
421
  __compute_args__(mbi, &_argc, _argv);
422
  return main(_argc,_argv);
423
}
424
 
425
 
426