Subversion Repositories shark

Rev

Rev 3 | Rev 38 | 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
 ------------
29 pj 24
 CVS :        $Id: func.h,v 1.2 2002-11-11 08:36:01 pj Exp $
2 pj 25
 
26
 File:        $File$
29 pj 27
 Revision:    $Revision: 1.2 $
28
 Last update: $Date: 2002-11-11 08:36:01 $
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
 
92
/*---------------------------------------------------------------------*/
93
/* Kernel global functions: initialization & termination...            */
94
/*---------------------------------------------------------------------*/
95
 
96
/*+ this function is called by __kernel_init__.
97
    It register the modules in the system at init time +*/
98
TIME __kernel_register_levels__(void *arg);
99
 
100
/*+ This function returns a level_des **. the value returned shall be
101
    used to register a level module. The function shall be called only at
102
    module registration time. It assume that the system is not yet
103
    initialized, so we shall not call sys_abort...                     +*/
104
LEVEL level_alloc_descriptor();
105
 
106
/*+ This function returns a resource_des **. the value returned shall be
107
    used to register a resource module. The function shall be called only at
108
    module registration time. It assume that the system is not yet
109
    initialized, so we shall not call sys_abort...                     +*/
110
RLEVEL resource_alloc_descriptor();
111
 
112
/*+ This function compute the command line parameters from the multiboot_info
113
    NOTE: this function modify the multiboot struct, so this function and
114
    __call_main__ are mutually exclusives!!! +*/
115
void __compute_args__(struct multiboot_info *mbi, int *_argc, char **_argv);
116
 
117
/*+ This function calls the standard C main() function, with a
118
    parameter list up to 100 parameters                        +*/
119
int __call_main__(struct multiboot_info *mb);
120
 
121
/*+ This task initialize the system and calls the main() with
122
    __call_mail__ .
123
    It should be created by a level registered in the system by
124
    __kernel_register_levels__ +*/
125
TASK __init__(void *arg);
126
 
127
/*+ Use this function to post your own exit operations
128
    (when uses some defines contained in const.h) +*/
129
int sys_atrunlevel(void (*func_code)(void *),void *parm, BYTE when);
130
 
131
/*+ These functions can be used to set a nice (I hope) default
132
    signal handler. If not used, they are not linked.
133
    They returns -1 if an error occurred, as done by the
134
    sigaction primitive. +*/
135
int set_exchandler_grx();
136
int set_exchandler_text();
137
 
138
/*---------------------------------------------------------------------*/
29 pj 139
/* Kernel global functions: scheduler,                                 */
2 pj 140
/*---------------------------------------------------------------------*/
141
 
142
/*+ This is the generic scheduler.
143
    The scheduler calls the appropriates level schedulers and then
144
    dispatch the task chosen. +*/
145
void scheduler(void);
146
 
147
/*+ called in the events to force the system to execute the scheduler at
148
    the end of an event list +*/
149
void event_need_reschedule();
150
 
151
void task_makefree(void *ret);
152
void check_killed_async(void);
153
 
154
int guarantee();
155
 
156
void runlevel_init();
157
void call_runlevel_func(int runlevel, int aborting);
158
 
159
// in kill.c
160
void kill_user_tasks();
161
 
162
void event_resetepilogue();
163
 
164
 
165
void call_task_specific_data_destructors();
166
void task_specific_data_init();
167
 
168
// in kill.c
169
void register_cancellation_point(int (*func)(PID p, void *arg), void *arg);
170
 
171
// in signal.c
172
void register_interruptable_point(int (*func)(PID p, void *arg), void *arg);
173
 
174
 
175
/*---------------------------------------------------------------------*/
176
/* Kernel VM hooks                                                     */
177
/*---------------------------------------------------------------------*/
178
 
179
/* this hooks redefines the VM functions to use them into the kernel...
180
 
181
   the only VM functions called directly from the kernel are VM_init and
182
   VM_end
183
*/
184
 
185
/* Context management routines */
186
#define kern_context_create    ll_context_create
187
#define kern_context_delete    ll_context_delete
188
 
189
extern __inline__ CONTEXT kern_context_save()
190
{
191
  cli();
192
  return ll_context_from();
193
}
194
 
195
/*+ this functions are called every time a context is changed +*/
196
void kern_after_dispatch(void);
197
 
198
/* Warning: if modified, modify also:
199
   - task_join
200
   - cond_wait
201
   - cond_timedwait
202
   - internal_sem_wait
203
*/
204
extern __inline__ void kern_context_load(c)
205
{
206
  ll_context_to(c);
207
  kern_after_dispatch();
208
  sti();
209
}
210
 
211
 
212
/* Interrupt enabling/disabling */
213
#define kern_cli          cli
214
#define kern_sti          sti
215
 
216
/* Interrupt enabling/disabling with flag save */
217
#define kern_fsave        ll_fsave
218
#define kern_frestore     ll_frestore
219
 
220
/* interrupt handling */
221
#define kern_irq_unmask   VM_irq_unmask
222
#define kern_irq_mask     VM_irq_mask
223
 
224
extern __inline__ int kern_event_post(const struct timespec *time,
225
                                      void (*handler)(void *p),
226
                                      void *par)
227
{
228
  int e;
229
  e = event_post(*time,handler,par);
230
 
231
  if (e == -1)
232
    kern_raise(XNOMORE_EVENTS,exec_shadow);
233
 
234
  return e;
235
}
236
 
237
/*+ the default capacity timer used by the kernel... +*/
238
void capacity_timer(void *arg);
239
 
240
 
241
#define kern_printf message
242
 
243
/*---------------------------------------------------------------------*/
244
/* Kernel global functions: IRQ, errors and exception handling         */
245
/*---------------------------------------------------------------------*/
246
 
247
/*+ Generic exception trapping routine +*/
248
void act_exc(int code);
249
 
250
/*
251
 * User level interrupt/exception primitives
252
 */
253
 
254
/*+ Interrupt handler installation +*/
255
int handler_set(int no, void (*fast)(int), PID pi);
256
 
257
/*+ Interrupt handler removal      +*/
258
int handler_remove(int no);
259
 
260
 
261
/*---------------------------------------------------------------------*/
262
/* System management primitives                                        */
263
/*---------------------------------------------------------------------*/
264
 
265
/*+ Close the system & return to HOST OS.
266
    Can be called from all the tasks...
267
    The first time it is called it jumps to the global context
268
    The second time it jumps only if there are no system task remaining
269
    The error code passed is 0... (it is saved on the first call!!!) +*/
270
void sys_end(void);
271
 
272
/*+ Close the system & return to HOST OS.
273
    Can be called from all the tasks...
274
    The first time it is called it works as the sys_end
275
    The second time it jumps every time
276
    The error code passed is 0... +*/
277
void sys_abort(int err);
278
 
279
/* The system implements also exit and _exit as a redefinition of sys_end
280
   This is not the correct behaviour, and should be fixed.
281
   The definitions for these functions are in kernel/kern.c
282
*/
283
 
284
/*+ Print a message then call sys_abort(333).
285
    Can be called from all the tasks...  +*/
286
void sys_panic(const char * fmt, ...) __attribute__ ((format (printf, 1, 2)));
287
 
288
/*+ prints an error message (see perror.c) +*/
289
void perror (const char *s);
290
 
291
/*+ Convert a status in a string. Useful for sys_status and level_status +*/
292
char *status_to_a(WORD status);
293
 
294
/*+ this primitive prints the status of the system. cw contains a set of
295
    the statuses to be prompted... see const.h +*/
296
void sys_status(DWORD cw);
297
 
298
/*+ sys_status flags +*/
299
#define CLOCK_STATUS    1
300
#define SCHED_STATUS    2
301
#define MEM_STATUS      4
302
 
303
/*+ this primitive returns the time read from the system timer +*/
304
TIME sys_gettime(struct timespec *t);
305
 
306
/*---------------------------------------------------------------------*/
307
/* Jet management primitives                                           */
308
/*---------------------------------------------------------------------*/
309
 
310
/*+ This primitive returns the maximum execution time and the total
311
    execution time from the task_create or the last jet_delstat
312
    It returns also the number of instances to use to calculate the mean
313
    time and the current job execution time.
314
    The value returned is 0 if all ok, -1 if the PID is not correct or
315
    the task doesn't have the JET_ENABLE bit set.
316
+*/
317
int jet_getstat(PID p, TIME *sum, TIME *max, int *n, TIME *curr);
318
 
319
/*+ This primitive reset to 0 the maximum execution time and the mean
320
    execution time of the task p, and reset to 0 all the entries in
321
    jet_table.
322
    The value returned is 0 if all ok, -1 if the PID is not correct or
323
    the task doesn't have the JET_ENABLE bit set.                     +*/
324
int jet_delstat(PID p);
325
 
326
/*+ This primitive returns the last n values of the task execution time
327
    recorded after the last call to jet_gettable or jet_delstat.
328
    If n is
329
    <0 it will be set only the last values inserted in the table
330
       since the last call of jet_gettable.
331
    >0 it will be set up to JET_TABLE_DIM datas.
332
 
333
    The value returned is -1 if the PID is not correct or
334
    the task doesn't have the JET_ENABLE bit set, otherwise it returns the
335
    number of values set in the parameter table.
336
    (can be from 0 to JET_TABLE_DIM-1)
337
+*/
338
int jet_gettable(PID p, TIME *table, int n);
339
 
340
/*+ This function updates the jet information. +*/
341
void jet_update_slice(TIME t);
342
 
343
/*+ This function updates the jet information at the task end period
344
    it is called in task_endcycle and task_sleep +*/
345
void jet_update_endcycle();
346
 
347
/*---------------------------------------------------------------------*/
348
/* Task management primitives                                          */
349
/*---------------------------------------------------------------------*/
350
 
351
 
352
/*+ This primitive:
353
    - Reserve a task descriptor
354
    - Create the task based on the task model passed
355
    - Initialize the resources used by the task
356
    - Guarantees the task set
357
+*/
358
PID task_createn(char *name,      /*+ the symbolic name of the task +*/
359
                 TASK (*body)(),  /*+ a pointer to the task body    +*/
360
                 TASK_MODEL *m,   /*+ the task model                +*/
361
                                  /*+ the resources models, a list  +*/
362
                 ...);            /*+ of models terminated by NULL  +*/
363
 
364
 
365
/*+ a redefinition of task_createn +*/
366
extern __inline PID task_create(char *name, TASK (*body)(),
367
                                void *m, void *r)
368
{
369
   return task_createn(name, body, (TASK_MODEL *)m, (RES_MODEL *)r, NULL);
370
}
371
 
372
 
373
/* This function allow to create a set of tasks without guarantee.
374
   It must be called with interrupts disabled and it must be used with
375
   group_create_accept and group_create_reject.
376
 
377
   This function allocates a task descriptor and fills it.
378
   After that, the guarantee() function should be called to check for task(s)
379
   admission.
380
   Next, each task created with group_create must be accepted with a call to
381
   group_create_accept() or rejected with a call to group_create_reject.
382
 
383
   The function returns the PID of the allocated descriptor, or NIL(-1)
384
   if the descriptor cannot be allocated or some problems arises the creation.
385
   If -1 is returned, errno is set to a value that represent the error:
386
      ENO_AVAIL_TASK       -> no free descriptors available
387
      ENO_AVAIL_SCHEDLEVEL -> there were no scheduling modules that can handle
388
                              the TASK_MODEL *m passed as parameter
389
      ETASK_CREATE         -> there was an error during the creation of the
390
                              task into the scheduling module
391
      ENO_AVAIL_RESLEVEL   -> there were no resource modules that can handle
392
                              one of the RES_MODEL * passed as parameter
393
*/
394
PID group_create(char *name,
395
                 TASK (*body)(),
396
                 TASK_MODEL *m,
397
                 ...);
398
 
399
 
400
/*
401
  This function should be called when a task created with group_create
402
  is successfully guaranteed and accepted in the system.
403
  This function finish the creation process allocating the last resources
404
  for the task (i.e., the stack and the context).
405
  it returns:
406
 
407
  -1 if something goes wrong. In this case, THE TASK IS AUTOMATICALLY REJECTED
408
     AND THE GROUP_CREATE_REJECT MUST NOT BE CALLED.
409
     errno is set to a value that explains the problem occurred:
410
 
411
     ENO_AVAIL_STACK_MEM -> No stack memory available for the task
412
     ENO_AVAIL_TSS       -> No context available for the task (This is a
413
                            CRITICAL error, and usually never happens...)
414
*/
415
int group_create_accept(PID i, TASK_MODEL *m);
416
 
417
/*
418
  This function should be called when a task created with group_create
419
  can not be successfully guaranteed.
420
  This function reject the task from the system.
421
  You cannot use the PID of a rejected task after this call.
422
*/
423
void group_create_reject(PID i);
424
 
425
/*+
426
  It blocks all explicit activation of a task made with task_activate and
427
  group_activate. These activations are registered in an internal counter,
428
  returned by task_unblock_activation.
429
  it returns 0 if all ok, or -1 otherwise. errno is set accordingly.
430
+*/
431
int task_block_activation(PID p);
432
 
433
/*+
434
  It unblocks all explicit activations of a task, and returns the number of
435
  "frozen" activations. It not call the task_activate!!!!
436
  it returns -1 if an error occurs. errno is set accordingly.
437
+*/
438
int task_unblock_activation(PID p);
439
 
440
 
441
/*+ Activate a task specified via pid returned from task_create +*/
442
int task_activate(PID pid);
443
 
444
/*+ Kill a task specified via pid returned from task_create +*/
445
int task_kill(PID pid);
446
 
447
/*+
448
  This primitive autokills the excuting task; it was used to avoid
449
  that returning from a task cause a jmp to an unpredictable location.
450
 
451
  Now it is obsolete, the task_create_stub do all the works.
452
 
453
  It is used by the Posix layer to implement pthread_exit
454
+*/
455
void task_abort(void *returnvalue);
456
 
457
/*+ Creates a cancellation point in the calling task +*/
458
void task_testcancel(void);
459
 
460
/*+ Set the cancellation state of the task +*/
461
int task_setcancelstate(int state, int *oldstate);
462
 
463
/*+ Set the cancellation type of the task +*/
464
int task_setcanceltype(int type, int *oldtype);
465
 
466
/*+ this function suspends execution of the calling task until the target
467
    task terminates, unless the target task has already terminated.
468
    It works like the pthread_join +*/
469
int task_join(PID p, void **value);
470
 
471
/*+ this function set the detach state of a task to joinable. This function
472
    is not present in Posix standard...
473
    returns ESRCH if p is non correct +*/
474
int task_joinable(PID p);
475
 
476
/*+ this function set the detach state of a task to detached. This function
477
    works as the posix's pthread_detach
478
    returns EINVAL if p can't be joined (or currently a task has done a
479
    join on it (condition not provided in posix)
480
    ESRCH if p is not correct +*/
481
int task_unjoinable(PID p);
482
 
483
/*+ Disable the preemption mechanism on the task.
484
    This primitive is very dangerous!!!!         +*/
485
void task_nopreempt(void);
486
 
487
/*+ Enable the preemption mechanism on the task. +*/
488
void task_preempt(void);
489
 
490
/*+ This function signals to the kernel that the current istance of
491
    the task (periodic or aperiodic) is ended; so the task can be
492
    suspended until it is activated again. Pending activations may be saved
493
    depending on the task model +*/
494
void task_endcycle(void);
495
 
496
/*+ This function suspend the actual task until an explicit activation
497
    Pending activations are discarded +*/
498
void task_sleep(void);
499
 
500
/*+ This primitives refers the group id which is supplied
501
    by the application, not by the kernel                 +*/
502
int group_activate(WORD g);
503
int group_kill(WORD g);
504
 
505
 
506
/*---------------------------------------------------------------------*/
507
/* Mutex primitives                                                    */
508
/*---------------------------------------------------------------------*/
509
 
510
/* This primitives manages a mutex in the system.
511
   The behavior of the functions is similar to the POSIX ones. */
512
 
513
 
514
/*+ Alloc a mutex descriptor +*/
515
int mutex_init(mutex_t *mutex, const mutexattr_t *attr);
516
 
517
/*+ Free a mutex descriptor  +*/
518
int mutex_destroy(mutex_t *mutex);
519
 
520
/*+ Block wait               +*/
521
int mutex_lock(mutex_t *mutex);
522
 
523
/*+ Non-block wait           +*/
524
int mutex_trylock(mutex_t *mutex);
525
 
526
/*+ unlock primitive +*/
527
int mutex_unlock(mutex_t *mutex);
528
 
529
/*---------------------------------------------------------------------*/
530
/* Condition variables                                                 */
531
/*---------------------------------------------------------------------*/
532
 
533
/*+ Initialization of the condition variable +*/
534
int cond_init(cond_t *cond);
535
 
536
/*+ free a condition variable descriptor +*/
537
int cond_destroy(cond_t *cond);
538
 
539
/*+ signal on a condition variable, it unlocks only one task +*/
540
int cond_signal(cond_t *cond);
541
 
542
/*+ broadcast on a condition variable, it unlocks all the blocked tasks +*/
543
int cond_broadcast(cond_t *cond);
544
 
545
/*+ wait on a condition variable +*/
546
int cond_wait(cond_t *cond, mutex_t *mutex);
547
 
548
/*+ wait on a condition variable (with timer) +*/
549
int cond_timedwait(cond_t *cond, mutex_t *mutex,
550
                   const struct timespec *abstime);
551
 
552
/*---------------------------------------------------------------------*/
553
/* Task specific data primitives                                       */
554
/*---------------------------------------------------------------------*/
555
 
556
/* they are similar to the POSIX standard */
557
 
558
int task_key_create(task_key_t *key, void (*destructor)(void *));
559
void *task_getspecific(task_key_t key);
560
int task_setspecific(task_key_t key, const void *value);
561
int task_key_delete(task_key_t key);
562
 
563
/*---------------------------------------------------------------------*/
564
/* Task cancellation handlers                                          */
565
/*---------------------------------------------------------------------*/
566
 
567
/*+ push the specified cancellation cleanup handler routine onto
568
    the cancellation cleanup stack
569
void task_cleanup_push(void (*routine)(void *), void *arg); +*/
570
#define task_cleanup_push(rtn,arg) { \
571
        struct _task_handler_rec __cleanup_handler, **__head; \
572
        __cleanup_handler.f = rtn; \
573
        __cleanup_handler.a = arg; \
574
        __head = task_getspecific(0); \
575
        __cleanup_handler.next = *__head; \
576
        *__head = &__cleanup_handler;
577
 
578
/*+
579
    removes the routine at the top of the cancellation cleanup stack
580
    of the calling thread
581
void task_cleanup_pop(int execute); +*/
582
#define task_cleanup_pop(ex) \
583
        *__head = __cleanup_handler.next; \
584
        if (ex) (*__cleanup_handler.f) (__cleanup_handler.a); \
585
}
586
 
587
#endif /* __FUNC_H__ */