Subversion Repositories shark

Rev

Rev 912 | 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
 *   Massimiliano Giorgi <massy@gandalf.sssup.it>
11
 *   Luca Abeni          <luca@gandalf.sssup.it>
12
 *   (see the web pages for full authors list)
13
 *
14
 * ReTiS Lab (Scuola Superiore S.Anna - Pisa - Italy)
15
 *
16
 * http://www.sssup.it
17
 * http://retis.sssup.it
18
 * http://shark.sssup.it
19
 */
20
 
21
 
22
/**
23
 ------------
923 pj 24
 CVS :        $Id: func.h,v 1.18 2005-01-08 14:52:11 pj Exp $
2 pj 25
 
26
 File:        $File$
923 pj 27
 Revision:    $Revision: 1.18 $
28
 Last update: $Date: 2005-01-08 14:52:11 $
2 pj 29
 ------------
30
 
31
Kernel functions:
32
 
33
- Debug stuff
34
 
35
- Primitives called at initialization time
36
 
37
- Kernel global functions (scheduler, queues)
38
 
39
- Kernel VM hooks
40
 
41
- IRQ, errors & exception handling
42
 
43
- System management primitives
44
 
45
- Jet management primitives
46
 
47
- Task management primitives
48
 
49
- Mutex primitives
50
 
51
**/
52
 
53
/*
54
 * Copyright (C) 2000 Paolo Gai
55
 *
56
 * This program is free software; you can redistribute it and/or modify
57
 * it under the terms of the GNU General Public License as published by
58
 * the Free Software Foundation; either version 2 of the License, or
59
 * (at your option) any later version.
60
 *
61
 * This program is distributed in the hope that it will be useful,
62
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
63
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
64
 * GNU General Public License for more details.
65
 *
66
 * You should have received a copy of the GNU General Public License
67
 * along with this program; if not, write to the Free Software
68
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
69
 *
70
 */
71
 
72
#ifndef __KERNEL_FUNC_H__
73
#define __KERNEL_FUNC_H__
74
 
75
#include <ll/ll.h>
76
#include <ll/stdio.h>
77
#include <kernel/types.h>
78
#include <kernel/model.h>
79
#include <kernel/mem.h>
80
#include <signal.h>
81
#include <kernel/var.h>
82
#include <errno.h>
83
 
84
 
85
/*---------------------------------------------------------------------*/
86
/* Debug stuff                                                         */
87
/*---------------------------------------------------------------------*/
88
 
89
/* if a source use printk() it should include log.h not func.h */
90
#include <kernel/log.h>
91
 
79 pj 92
#include "ll/sys/cdefs.h"
93
 
94
__BEGIN_DECLS
95
 
2 pj 96
/*---------------------------------------------------------------------*/
97
/* Kernel global functions: initialization & termination...            */
98
/*---------------------------------------------------------------------*/
99
 
100
/*+ this function is called by __kernel_init__.
101
    It register the modules in the system at init time +*/
102
TIME __kernel_register_levels__(void *arg);
103
 
104
/*+ This function returns a level_des **. the value returned shall be
38 pj 105
    used to register a level module.
2 pj 106
 
38 pj 107
    The function is usually called at module registration time.  The
108
    function can also be called when the system is already started, to
109
    allow the implementation of dynamic module registration.  
110
 
111
    The argument must be the size of the data block that have to be allocated
112
 
113
    The function returns the number of the descriptor allocated for the module
114
    or -1 in case there are no free descriptors.
115
 
116
    The function also reserves a descriptor with size s, initialized
117
    with default function pointers.
118
 
119
+*/
120
LEVEL level_alloc_descriptor(size_t s);
121
 
122
/*+ This function release a level descriptor previously allocated using
123
  level_alloc_descriptor().
124
 
125
  The function returns 0 if the level has been freed, or -1 if someone is
126
  using it, -2 if the level has never been registered.
127
 
128
+*/
129
int level_free_descriptor(LEVEL l);
130
 
131
/* Call this if you want to say that your module is using module l
132
   (e.g., for calling its private functions) */
133
int level_use_descriptor(LEVEL l);
134
 
135
/* Call this when you no more need the module l */
136
int level_unuse_descriptor(LEVEL l);
137
 
2 pj 138
/*+ This function returns a resource_des **. the value returned shall be
139
    used to register a resource module. The function shall be called only at
923 pj 140
    module registration time. +*/
2 pj 141
RLEVEL resource_alloc_descriptor();
142
 
143
/*+ This function compute the command line parameters from the multiboot_info
144
    NOTE: this function modify the multiboot struct, so this function and
145
    __call_main__ are mutually exclusives!!! +*/
146
void __compute_args__(struct multiboot_info *mbi, int *_argc, char **_argv);
147
 
148
/*+ This function calls the standard C main() function, with a
149
    parameter list up to 100 parameters                        +*/
150
int __call_main__(struct multiboot_info *mb);
151
 
152
/*+ This task initialize the system and calls the main() with
153
    __call_mail__ .
154
    It should be created by a level registered in the system by
155
    __kernel_register_levels__ +*/
156
TASK __init__(void *arg);
157
 
158
/*+ Use this function to post your own exit operations
159
    (when uses some defines contained in const.h) +*/
160
int sys_atrunlevel(void (*func_code)(void *),void *parm, BYTE when);
161
 
162
/*---------------------------------------------------------------------*/
29 pj 163
/* Kernel global functions: scheduler,                                 */
2 pj 164
/*---------------------------------------------------------------------*/
165
 
166
/*+ This is the generic scheduler.
167
    The scheduler calls the appropriates level schedulers and then
168
    dispatch the task chosen. +*/
169
void scheduler(void);
170
 
171
/*+ called in the events to force the system to execute the scheduler at
172
    the end of an event list +*/
173
void event_need_reschedule();
174
 
175
void task_makefree(void *ret);
176
void check_killed_async(void);
177
 
178
int guarantee();
179
 
38 pj 180
void levels_init(void); /* see init.c */
181
 
2 pj 182
void runlevel_init();
183
void call_runlevel_func(int runlevel, int aborting);
184
 
185
// in kill.c
186
void kill_user_tasks();
187
 
188
void event_resetepilogue();
189
 
190
 
191
void call_task_specific_data_destructors();
192
void task_specific_data_init();
193
 
194
// in kill.c
195
void register_cancellation_point(int (*func)(PID p, void *arg), void *arg);
196
 
197
// in signal.c
198
void register_interruptable_point(int (*func)(PID p, void *arg), void *arg);
199
 
200
 
201
/*---------------------------------------------------------------------*/
202
/* Kernel VM hooks                                                     */
203
/*---------------------------------------------------------------------*/
204
 
205
/* this hooks redefines the VM functions to use them into the kernel...
206
 
207
   the only VM functions called directly from the kernel are VM_init and
208
   VM_end
209
*/
210
 
646 mauro 211
/* Advanced Timer adjust */
212
#define kern_scale_timer       ll_scale_advtimer
213
 
620 mauro 214
/* Exit mode selection */
215
#define sys_set_reboot         ll_set_reboot
216
 
2 pj 217
/* Context management routines */
218
#define kern_context_create    ll_context_create
219
#define kern_context_delete    ll_context_delete
220
 
221
extern __inline__ CONTEXT kern_context_save()
222
{
223
  cli();
224
  return ll_context_from();
225
}
226
 
227
/*+ this functions are called every time a context is changed +*/
228
void kern_after_dispatch(void);
229
 
230
/* Warning: if modified, modify also:
231
   - task_join
232
   - cond_wait
233
   - cond_timedwait
234
   - internal_sem_wait
235
*/
82 pj 236
extern __inline__ void kern_context_load(CONTEXT c)
2 pj 237
{
238
  ll_context_to(c);
239
  kern_after_dispatch();
240
  sti();
241
}
242
 
243
 
244
/* Interrupt enabling/disabling */
245
#define kern_cli          cli
246
#define kern_sti          sti
247
 
248
/* Interrupt enabling/disabling with flag save */
249
#define kern_fsave        ll_fsave
250
#define kern_frestore     ll_frestore
251
 
252
/* interrupt handling */
253
#define kern_irq_unmask   VM_irq_unmask
254
#define kern_irq_mask     VM_irq_mask
255
 
256
extern __inline__ int kern_event_post(const struct timespec *time,
257
                                      void (*handler)(void *p),
258
                                      void *par)
259
{
260
  int e;
261
  e = event_post(*time,handler,par);
262
 
263
  if (e == -1)
264
    kern_raise(XNOMORE_EVENTS,exec_shadow);
265
 
266
  return e;
267
}
268
 
38 pj 269
#define kern_event_delete event_delete
270
 
2 pj 271
/*+ the default capacity timer used by the kernel... +*/
272
void capacity_timer(void *arg);
273
 
274
 
275
#define kern_printf message
276
 
38 pj 277
extern __inline__ TIME kern_gettime(struct timespec *t)
278
{
45 pj 279
  return ll_gettime(TIME_NEW, t);
38 pj 280
}
281
 
282
 
283
 
2 pj 284
/*---------------------------------------------------------------------*/
38 pj 285
/* Kernel global functions: IRQ handling                               */
2 pj 286
/*---------------------------------------------------------------------*/
287
 
288
/*+ Interrupt handler installation +*/
496 giacomo 289
int handler_set(int no, void (*fast)(int), PID pi, BYTE lock);
2 pj 290
 
291
/*+ Interrupt handler removal      +*/
292
int handler_remove(int no);
293
 
294
 
295
/*---------------------------------------------------------------------*/
296
/* System management primitives                                        */
297
/*---------------------------------------------------------------------*/
298
 
923 pj 299
void exit(int status);
300
void _exit(int status);
2 pj 301
 
923 pj 302
/*+ Shuts down the system when in RUNLEVEL SHUTDOWN +*/
571 giacomo 303
void sys_abort_shutdown(int err);
304
 
923 pj 305
/*+ Print a message then call exit(333).
2 pj 306
    Can be called from all the tasks...  +*/
307
void sys_panic(const char * fmt, ...) __attribute__ ((format (printf, 1, 2)));
308
 
309
/*+ prints an error message (see perror.c) +*/
310
void perror (const char *s);
311
 
312
/*+ this primitive returns the time read from the system timer +*/
313
TIME sys_gettime(struct timespec *t);
314
 
158 pj 315
/*+ this primitive can be used to set a message that will be printed
316
    at shutdown +*/
317
int sys_shutdown_message(char *fmt,...);
318
 
2 pj 319
/*---------------------------------------------------------------------*/
320
/* Jet management primitives                                           */
321
/*---------------------------------------------------------------------*/
322
 
323
/*+ This primitive returns the maximum execution time and the total
324
    execution time from the task_create or the last jet_delstat
325
    It returns also the number of instances to use to calculate the mean
326
    time and the current job execution time.
327
    The value returned is 0 if all ok, -1 if the PID is not correct or
328
    the task doesn't have the JET_ENABLE bit set.
329
+*/
330
int jet_getstat(PID p, TIME *sum, TIME *max, int *n, TIME *curr);
331
 
332
/*+ This primitive reset to 0 the maximum execution time and the mean
333
    execution time of the task p, and reset to 0 all the entries in
334
    jet_table.
335
    The value returned is 0 if all ok, -1 if the PID is not correct or
336
    the task doesn't have the JET_ENABLE bit set.                     +*/
337
int jet_delstat(PID p);
338
 
339
/*+ This primitive returns the last n values of the task execution time
340
    recorded after the last call to jet_gettable or jet_delstat.
341
    If n is
342
    <0 it will be set only the last values inserted in the table
343
       since the last call of jet_gettable.
344
    >0 it will be set up to JET_TABLE_DIM datas.
345
 
346
    The value returned is -1 if the PID is not correct or
347
    the task doesn't have the JET_ENABLE bit set, otherwise it returns the
348
    number of values set in the parameter table.
349
    (can be from 0 to JET_TABLE_DIM-1)
350
+*/
351
int jet_gettable(PID p, TIME *table, int n);
352
 
353
/*+ This function updates the jet information. +*/
354
void jet_update_slice(TIME t);
355
 
356
/*+ This function updates the jet information at the task end period
357
    it is called in task_endcycle and task_sleep +*/
358
void jet_update_endcycle();
359
 
360
/*---------------------------------------------------------------------*/
38 pj 361
/* Internal Macros                                                     */
362
/*---------------------------------------------------------------------*/
363
 
364
extern __inline__ void kern_epilogue_macro(void)
365
{
366
  TIME tx;    /* a dummy used for time computation             */
367
  struct timespec ty; /* a dummy used for time computation     */
368
 
369
  kern_gettime(&schedule_time);
370
 
371
  /* manage the capacity event */
372
  SUBTIMESPEC(&schedule_time, &cap_lasttime, &ty);
373
  tx = TIMESPEC2USEC(&ty);
393 giacomo 374
  if (proc_table[exec_shadow].control & CONTROL_CAP) proc_table[exec_shadow].avail_time -= tx;
38 pj 375
  jet_update_slice(tx);
376
 
377
  /* if the event didn't fire before, we delete it. */
378
  if (cap_timer != NIL) {
379
    kern_event_delete(cap_timer);
380
    cap_timer = NIL;
381
  }
382
}
383
 
384
/* This function is called by the kernel into kern.c to register a default
385
   exception handler */
386
int set_default_exception_handler(void);
567 giacomo 387
int remove_default_exception_handler(void);
38 pj 388
 
389
/*---------------------------------------------------------------------*/
2 pj 390
/* Task management primitives                                          */
391
/*---------------------------------------------------------------------*/
392
 
393
 
394
/*+ This primitive:
395
    - Reserve a task descriptor
396
    - Create the task based on the task model passed
397
    - Initialize the resources used by the task
398
    - Guarantees the task set
399
+*/
400
PID task_createn(char *name,      /*+ the symbolic name of the task +*/
401
                 TASK (*body)(),  /*+ a pointer to the task body    +*/
402
                 TASK_MODEL *m,   /*+ the task model                +*/
403
                                  /*+ the resources models, a list  +*/
404
                 ...);            /*+ of models terminated by NULL  +*/
405
 
406
 
407
/*+ a redefinition of task_createn +*/
408
extern __inline PID task_create(char *name, TASK (*body)(),
409
                                void *m, void *r)
410
{
411
   return task_createn(name, body, (TASK_MODEL *)m, (RES_MODEL *)r, NULL);
412
}
413
 
414
 
415
/* This function allow to create a set of tasks without guarantee.
416
   It must be called with interrupts disabled and it must be used with
417
   group_create_accept and group_create_reject.
418
 
419
   This function allocates a task descriptor and fills it.
420
   After that, the guarantee() function should be called to check for task(s)
421
   admission.
422
   Next, each task created with group_create must be accepted with a call to
423
   group_create_accept() or rejected with a call to group_create_reject.
424
 
425
   The function returns the PID of the allocated descriptor, or NIL(-1)
426
   if the descriptor cannot be allocated or some problems arises the creation.
427
   If -1 is returned, errno is set to a value that represent the error:
428
      ENO_AVAIL_TASK       -> no free descriptors available
429
      ENO_AVAIL_SCHEDLEVEL -> there were no scheduling modules that can handle
430
                              the TASK_MODEL *m passed as parameter
431
      ETASK_CREATE         -> there was an error during the creation of the
432
                              task into the scheduling module
433
      ENO_AVAIL_RESLEVEL   -> there were no resource modules that can handle
434
                              one of the RES_MODEL * passed as parameter
435
*/
436
PID group_create(char *name,
437
                 TASK (*body)(),
438
                 TASK_MODEL *m,
439
                 ...);
440
 
441
 
442
/*
443
  This function should be called when a task created with group_create
444
  is successfully guaranteed and accepted in the system.
445
  This function finish the creation process allocating the last resources
446
  for the task (i.e., the stack and the context).
447
  it returns:
448
 
449
  -1 if something goes wrong. In this case, THE TASK IS AUTOMATICALLY REJECTED
450
     AND THE GROUP_CREATE_REJECT MUST NOT BE CALLED.
451
     errno is set to a value that explains the problem occurred:
452
 
453
     ENO_AVAIL_STACK_MEM -> No stack memory available for the task
454
     ENO_AVAIL_TSS       -> No context available for the task (This is a
455
                            CRITICAL error, and usually never happens...)
456
*/
457
int group_create_accept(PID i, TASK_MODEL *m);
458
 
459
/*
460
  This function should be called when a task created with group_create
461
  can not be successfully guaranteed.
462
  This function reject the task from the system.
463
  You cannot use the PID of a rejected task after this call.
464
*/
465
void group_create_reject(PID i);
466
 
467
/*+
468
  It blocks all explicit activation of a task made with task_activate and
469
  group_activate. These activations are registered in an internal counter,
470
  returned by task_unblock_activation.
471
  it returns 0 if all ok, or -1 otherwise. errno is set accordingly.
472
+*/
473
int task_block_activation(PID p);
474
 
475
/*+
476
  It unblocks all explicit activations of a task, and returns the number of
477
  "frozen" activations. It not call the task_activate!!!!
478
  it returns -1 if an error occurs. errno is set accordingly.
479
+*/
480
int task_unblock_activation(PID p);
481
 
482
 
483
/*+ Activate a task specified via pid returned from task_create +*/
484
int task_activate(PID pid);
485
 
690 anton 486
/*+ Activate a task specified via pid from task_create at time t +*/
487
int task_activate_at(PID pid, struct timespec *t);
488
 
2 pj 489
/*+ Kill a task specified via pid returned from task_create +*/
490
int task_kill(PID pid);
491
 
492
/*+
493
  This primitive autokills the excuting task; it was used to avoid
494
  that returning from a task cause a jmp to an unpredictable location.
495
 
496
  Now it is obsolete, the task_create_stub do all the works.
497
 
498
  It is used by the Posix layer to implement pthread_exit
499
+*/
500
void task_abort(void *returnvalue);
501
 
502
/*+ Creates a cancellation point in the calling task +*/
503
void task_testcancel(void);
504
 
505
/*+ Set the cancellation state of the task +*/
506
int task_setcancelstate(int state, int *oldstate);
507
 
508
/*+ Set the cancellation type of the task +*/
509
int task_setcanceltype(int type, int *oldtype);
510
 
511
/*+ this function suspends execution of the calling task until the target
512
    task terminates, unless the target task has already terminated.
513
    It works like the pthread_join +*/
514
int task_join(PID p, void **value);
515
 
516
/*+ this function set the detach state of a task to joinable. This function
517
    is not present in Posix standard...
518
    returns ESRCH if p is non correct +*/
519
int task_joinable(PID p);
520
 
521
/*+ this function set the detach state of a task to detached. This function
522
    works as the posix's pthread_detach
523
    returns EINVAL if p can't be joined (or currently a task has done a
524
    join on it (condition not provided in posix)
525
    ESRCH if p is not correct +*/
526
int task_unjoinable(PID p);
527
 
528
/*+ Disable the preemption mechanism on the task.
529
    This primitive is very dangerous!!!!         +*/
530
void task_nopreempt(void);
531
 
532
/*+ Enable the preemption mechanism on the task. +*/
533
void task_preempt(void);
534
 
38 pj 535
/*+ sends a message to the scheduling module that is handling the task +*/
208 giacomo 536
int task_message(void *m, PID p, int reschedule);
38 pj 537
 
2 pj 538
/*+ This function signals to the kernel that the current istance of
539
    the task (periodic or aperiodic) is ended; so the task can be
540
    suspended until it is activated again. Pending activations may be saved
541
    depending on the task model +*/
38 pj 542
extern __inline__ void task_endcycle(void)
543
{
912 pj 544
  task_testcancel();
210 giacomo 545
  task_message(NULL, NIL, 1);
38 pj 546
}
2 pj 547
 
208 giacomo 548
/*+ This function signals to the kernel that the current istance of
549
    the task (periodic or aperiodic) is ended; so the task can be
550
    suspended until it is activated again. Pending activations may be saved
551
    depending on the task model +*/
552
extern __inline__ void task_disable(PID p)
553
{
554
  task_message((void *)(1), p, 0);
555
}
556
 
2 pj 557
/*+ This primitives refers the group id which is supplied
558
    by the application, not by the kernel                 +*/
559
int group_activate(WORD g);
690 anton 560
int group_activate_at(WORD g, struct timespec *t);
2 pj 561
int group_kill(WORD g);
562
 
563
 
564
/*---------------------------------------------------------------------*/
565
/* Mutex primitives                                                    */
566
/*---------------------------------------------------------------------*/
567
 
568
/* This primitives manages a mutex in the system.
569
   The behavior of the functions is similar to the POSIX ones. */
570
 
571
 
572
/*+ Alloc a mutex descriptor +*/
573
int mutex_init(mutex_t *mutex, const mutexattr_t *attr);
574
 
575
/*+ Free a mutex descriptor  +*/
576
int mutex_destroy(mutex_t *mutex);
577
 
578
/*+ Block wait               +*/
579
int mutex_lock(mutex_t *mutex);
580
 
581
/*+ Non-block wait           +*/
582
int mutex_trylock(mutex_t *mutex);
583
 
584
/*+ unlock primitive +*/
585
int mutex_unlock(mutex_t *mutex);
586
 
587
/*---------------------------------------------------------------------*/
588
/* Condition variables                                                 */
589
/*---------------------------------------------------------------------*/
590
 
591
/*+ Initialization of the condition variable +*/
592
int cond_init(cond_t *cond);
593
 
594
/*+ free a condition variable descriptor +*/
595
int cond_destroy(cond_t *cond);
596
 
597
/*+ signal on a condition variable, it unlocks only one task +*/
598
int cond_signal(cond_t *cond);
599
 
600
/*+ broadcast on a condition variable, it unlocks all the blocked tasks +*/
601
int cond_broadcast(cond_t *cond);
602
 
603
/*+ wait on a condition variable +*/
604
int cond_wait(cond_t *cond, mutex_t *mutex);
605
 
606
/*+ wait on a condition variable (with timer) +*/
607
int cond_timedwait(cond_t *cond, mutex_t *mutex,
608
                   const struct timespec *abstime);
609
 
610
/*---------------------------------------------------------------------*/
611
/* Task specific data primitives                                       */
612
/*---------------------------------------------------------------------*/
613
 
614
/* they are similar to the POSIX standard */
615
 
616
int task_key_create(task_key_t *key, void (*destructor)(void *));
617
void *task_getspecific(task_key_t key);
618
int task_setspecific(task_key_t key, const void *value);
619
int task_key_delete(task_key_t key);
620
 
621
/*---------------------------------------------------------------------*/
622
/* Task cancellation handlers                                          */
623
/*---------------------------------------------------------------------*/
624
 
625
/*+ push the specified cancellation cleanup handler routine onto
626
    the cancellation cleanup stack
627
void task_cleanup_push(void (*routine)(void *), void *arg); +*/
628
#define task_cleanup_push(rtn,arg) { \
629
        struct _task_handler_rec __cleanup_handler, **__head; \
630
        __cleanup_handler.f = rtn; \
631
        __cleanup_handler.a = arg; \
632
        __head = task_getspecific(0); \
633
        __cleanup_handler.next = *__head; \
634
        *__head = &__cleanup_handler;
635
 
636
/*+
637
    removes the routine at the top of the cancellation cleanup stack
638
    of the calling thread
639
void task_cleanup_pop(int execute); +*/
640
#define task_cleanup_pop(ex) \
641
        *__head = __cleanup_handler.next; \
642
        if (ex) (*__cleanup_handler.f) (__cleanup_handler.a); \
643
}
644
 
79 pj 645
__END_DECLS
2 pj 646
#endif /* __FUNC_H__ */