Subversion Repositories shark

Rev

Details | 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
 ------------
24
 CVS :        $Id: func.h,v 1.1.1.1 2002-03-29 14:12:51 pj Exp $
25
 
26
 File:        $File$
27
 Revision:    $Revision: 1.1.1.1 $
28
 Last update: $Date: 2002-03-29 14:12:51 $
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
#if 0
93
#ifdef __DEBUG_ON__
94
#define printk(fmt,args...)    \
95
        VM_printf(fmt,##args)
96
#else
97
#define printk(fmt,args...)
98
#endif
99
#endif
100
 
101
/*---------------------------------------------------------------------*/
102
/* Kernel global functions: initialization & termination...            */
103
/*---------------------------------------------------------------------*/
104
 
105
/*+ this function is called by __kernel_init__.
106
    It register the modules in the system at init time +*/
107
TIME __kernel_register_levels__(void *arg);
108
 
109
/*+ This function returns a level_des **. the value returned shall be
110
    used to register a level module. The function shall be called only at
111
    module registration time. It assume that the system is not yet
112
    initialized, so we shall not call sys_abort...                     +*/
113
LEVEL level_alloc_descriptor();
114
 
115
/*+ This function returns a resource_des **. the value returned shall be
116
    used to register a resource module. The function shall be called only at
117
    module registration time. It assume that the system is not yet
118
    initialized, so we shall not call sys_abort...                     +*/
119
RLEVEL resource_alloc_descriptor();
120
 
121
/*+ This function compute the command line parameters from the multiboot_info
122
    NOTE: this function modify the multiboot struct, so this function and
123
    __call_main__ are mutually exclusives!!! +*/
124
void __compute_args__(struct multiboot_info *mbi, int *_argc, char **_argv);
125
 
126
/*+ This function calls the standard C main() function, with a
127
    parameter list up to 100 parameters                        +*/
128
int __call_main__(struct multiboot_info *mb);
129
 
130
/*+ This task initialize the system and calls the main() with
131
    __call_mail__ .
132
    It should be created by a level registered in the system by
133
    __kernel_register_levels__ +*/
134
TASK __init__(void *arg);
135
 
136
/*+ Use this function to post your own exit operations
137
    (when uses some defines contained in const.h) +*/
138
int sys_atrunlevel(void (*func_code)(void *),void *parm, BYTE when);
139
 
140
/*+ These functions can be used to set a nice (I hope) default
141
    signal handler. If not used, they are not linked.
142
    They returns -1 if an error occurred, as done by the
143
    sigaction primitive. +*/
144
int set_exchandler_grx();
145
int set_exchandler_text();
146
 
147
/*---------------------------------------------------------------------*/
148
/* Kernel global functions: scheduler, queues                          */
149
/*---------------------------------------------------------------------*/
150
 
151
/*+ This is the generic scheduler.
152
    The scheduler calls the appropriates level schedulers and then
153
    dispatch the task chosen. +*/
154
void scheduler(void);
155
 
156
/*+ called in the events to force the system to execute the scheduler at
157
    the end of an event list +*/
158
void event_need_reschedule();
159
 
160
/* Simple QUEUE management functions */
161
void q_insert           (PID p, QUEUE *q);
162
void q_timespec_insert  (PID p, QUEUE *q);
163
void q_extract          (PID p, QUEUE *q);
164
PID  q_getfirst         (       QUEUE *q);
165
void q_insertfirst      (PID p, QUEUE *q);
166
 
167
 
168
/* QQUEUE management functions */
169
void qq_init            (       QQUEUE *q);
170
void qq_insert          (PID p, QQUEUE *q);
171
void qq_timespec_insert (PID p, QQUEUE *q);
172
void qq_extract         (PID p, QQUEUE *q);
173
PID  qq_getfirst        (       QQUEUE *q);
174
void qq_insertfirst     (PID p, QQUEUE *q);
175
void qq_insertlast      (PID p, QQUEUE *q);
176
PID  qq_queryfirst      (       QQUEUE *q);
177
PID  qq_querylast       (       QQUEUE *q);
178
 
179
 
180
void task_makefree(void *ret);
181
void check_killed_async(void);
182
 
183
int guarantee();
184
 
185
void runlevel_init();
186
void call_runlevel_func(int runlevel, int aborting);
187
 
188
// in kill.c
189
void kill_user_tasks();
190
 
191
void event_resetepilogue();
192
 
193
 
194
void call_task_specific_data_destructors();
195
void task_specific_data_init();
196
 
197
// in kill.c
198
void register_cancellation_point(int (*func)(PID p, void *arg), void *arg);
199
 
200
// in signal.c
201
void register_interruptable_point(int (*func)(PID p, void *arg), void *arg);
202
 
203
 
204
/*---------------------------------------------------------------------*/
205
/* Kernel VM hooks                                                     */
206
/*---------------------------------------------------------------------*/
207
 
208
/* this hooks redefines the VM functions to use them into the kernel...
209
 
210
   the only VM functions called directly from the kernel are VM_init and
211
   VM_end
212
*/
213
 
214
/* Context management routines */
215
#define kern_context_create    ll_context_create
216
#define kern_context_delete    ll_context_delete
217
 
218
extern __inline__ CONTEXT kern_context_save()
219
{
220
  cli();
221
  return ll_context_from();
222
}
223
 
224
 
225
 
226
#ifdef __TEST1__
227
extern int useds;
228
extern int testactive;
229
extern struct timespec s_send[];
230
#endif
231
 
232
 
233
/*+ this functions are called every time a context is changed +*/
234
void kern_after_dispatch(void);
235
 
236
/* Warning: if modified, modify also:
237
   - task_join
238
   - cond_wait
239
   - cond_timedwait
240
   - internal_sem_wait
241
*/
242
extern __inline__ void kern_context_load(c)
243
{
244
  ll_context_to(c);
245
  kern_after_dispatch();
246
 
247
  #ifdef __TEST1__
248
  if (testactive) ll_gettime(TIME_EXACT,&s_send[useds-1] );
249
  #endif
250
  sti();
251
}
252
 
253
 
254
/* Interrupt enabling/disabling */
255
#define kern_cli          cli
256
#define kern_sti          sti
257
 
258
/* Interrupt enabling/disabling with flag save */
259
#define kern_fsave        ll_fsave
260
#define kern_frestore     ll_frestore
261
 
262
/* interrupt handling */
263
#define kern_irq_unmask   VM_irq_unmask
264
#define kern_irq_mask     VM_irq_mask
265
 
266
extern __inline__ int kern_event_post(const struct timespec *time,
267
                                      void (*handler)(void *p),
268
                                      void *par)
269
{
270
  int e;
271
  e = event_post(*time,handler,par);
272
 
273
  if (e == -1)
274
    kern_raise(XNOMORE_EVENTS,exec_shadow);
275
 
276
  return e;
277
}
278
 
279
/*+ the default capacity timer used by the kernel... +*/
280
void capacity_timer(void *arg);
281
 
282
 
283
#define kern_printf message
284
 
285
/*---------------------------------------------------------------------*/
286
/* Kernel global functions: IRQ, errors and exception handling         */
287
/*---------------------------------------------------------------------*/
288
 
289
/*+ Generic exception trapping routine +*/
290
void act_exc(int code);
291
 
292
/*
293
 * User level interrupt/exception primitives
294
 */
295
 
296
/*+ Interrupt handler installation +*/
297
int handler_set(int no, void (*fast)(int), PID pi);
298
 
299
/*+ Interrupt handler removal      +*/
300
int handler_remove(int no);
301
 
302
 
303
/*---------------------------------------------------------------------*/
304
/* System management primitives                                        */
305
/*---------------------------------------------------------------------*/
306
 
307
/*+ Close the system & return to HOST OS.
308
    Can be called from all the tasks...
309
    The first time it is called it jumps to the global context
310
    The second time it jumps only if there are no system task remaining
311
    The error code passed is 0... (it is saved on the first call!!!) +*/
312
void sys_end(void);
313
 
314
/*+ Close the system & return to HOST OS.
315
    Can be called from all the tasks...
316
    The first time it is called it works as the sys_end
317
    The second time it jumps every time
318
    The error code passed is 0... +*/
319
void sys_abort(int err);
320
 
321
/* The system implements also exit and _exit as a redefinition of sys_end
322
   This is not the correct behaviour, and should be fixed.
323
   The definitions for these functions are in kernel/kern.c
324
*/
325
 
326
/*+ Print a message then call sys_abort(333).
327
    Can be called from all the tasks...  +*/
328
void sys_panic(const char * fmt, ...) __attribute__ ((format (printf, 1, 2)));
329
 
330
/*+ prints an error message (see perror.c) +*/
331
void perror (const char *s);
332
 
333
/*+ Convert a status in a string. Useful for sys_status and level_status +*/
334
char *status_to_a(WORD status);
335
 
336
/*+ this primitive prints the status of the system. cw contains a set of
337
    the statuses to be prompted... see const.h +*/
338
void sys_status(DWORD cw);
339
 
340
/*+ sys_status flags +*/
341
#define CLOCK_STATUS    1
342
#define SCHED_STATUS    2
343
#define MEM_STATUS      4
344
 
345
/*+ this primitive returns the time read from the system timer +*/
346
TIME sys_gettime(struct timespec *t);
347
 
348
/*---------------------------------------------------------------------*/
349
/* Jet management primitives                                           */
350
/*---------------------------------------------------------------------*/
351
 
352
/*+ This primitive returns the maximum execution time and the total
353
    execution time from the task_create or the last jet_delstat
354
    It returns also the number of instances to use to calculate the mean
355
    time and the current job execution time.
356
    The value returned is 0 if all ok, -1 if the PID is not correct or
357
    the task doesn't have the JET_ENABLE bit set.
358
+*/
359
int jet_getstat(PID p, TIME *sum, TIME *max, int *n, TIME *curr);
360
 
361
/*+ This primitive reset to 0 the maximum execution time and the mean
362
    execution time of the task p, and reset to 0 all the entries in
363
    jet_table.
364
    The value returned is 0 if all ok, -1 if the PID is not correct or
365
    the task doesn't have the JET_ENABLE bit set.                     +*/
366
int jet_delstat(PID p);
367
 
368
/*+ This primitive returns the last n values of the task execution time
369
    recorded after the last call to jet_gettable or jet_delstat.
370
    If n is
371
    <0 it will be set only the last values inserted in the table
372
       since the last call of jet_gettable.
373
    >0 it will be set up to JET_TABLE_DIM datas.
374
 
375
    The value returned is -1 if the PID is not correct or
376
    the task doesn't have the JET_ENABLE bit set, otherwise it returns the
377
    number of values set in the parameter table.
378
    (can be from 0 to JET_TABLE_DIM-1)
379
+*/
380
int jet_gettable(PID p, TIME *table, int n);
381
 
382
/*+ This function updates the jet information. +*/
383
void jet_update_slice(TIME t);
384
 
385
/*+ This function updates the jet information at the task end period
386
    it is called in task_endcycle and task_sleep +*/
387
void jet_update_endcycle();
388
 
389
/*---------------------------------------------------------------------*/
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
 
486
/*+ Kill a task specified via pid returned from task_create +*/
487
int task_kill(PID pid);
488
 
489
/*+
490
  This primitive autokills the excuting task; it was used to avoid
491
  that returning from a task cause a jmp to an unpredictable location.
492
 
493
  Now it is obsolete, the task_create_stub do all the works.
494
 
495
  It is used by the Posix layer to implement pthread_exit
496
+*/
497
void task_abort(void *returnvalue);
498
 
499
/*+ Creates a cancellation point in the calling task +*/
500
void task_testcancel(void);
501
 
502
/*+ Set the cancellation state of the task +*/
503
int task_setcancelstate(int state, int *oldstate);
504
 
505
/*+ Set the cancellation type of the task +*/
506
int task_setcanceltype(int type, int *oldtype);
507
 
508
/*+ this function suspends execution of the calling task until the target
509
    task terminates, unless the target task has already terminated.
510
    It works like the pthread_join +*/
511
int task_join(PID p, void **value);
512
 
513
/*+ this function set the detach state of a task to joinable. This function
514
    is not present in Posix standard...
515
    returns ESRCH if p is non correct +*/
516
int task_joinable(PID p);
517
 
518
/*+ this function set the detach state of a task to detached. This function
519
    works as the posix's pthread_detach
520
    returns EINVAL if p can't be joined (or currently a task has done a
521
    join on it (condition not provided in posix)
522
    ESRCH if p is not correct +*/
523
int task_unjoinable(PID p);
524
 
525
/*+ Disable the preemption mechanism on the task.
526
    This primitive is very dangerous!!!!         +*/
527
void task_nopreempt(void);
528
 
529
/*+ Enable the preemption mechanism on the task. +*/
530
void task_preempt(void);
531
 
532
/*+ This function signals to the kernel that the current istance of
533
    the task (periodic or aperiodic) is ended; so the task can be
534
    suspended until it is activated again. Pending activations may be saved
535
    depending on the task model +*/
536
void task_endcycle(void);
537
 
538
/*+ This function suspend the actual task until an explicit activation
539
    Pending activations are discarded +*/
540
void task_sleep(void);
541
 
542
/*+ This function suspend the actual task for a minimum delay time +*/
543
void task_delay(DWORD delay);
544
 
545
/*+ This primitives refers the group id which is supplied
546
    by the application, not by the kernel                 +*/
547
int group_activate(WORD g);
548
int group_kill(WORD g);
549
 
550
 
551
/*---------------------------------------------------------------------*/
552
/* Mutex primitives                                                    */
553
/*---------------------------------------------------------------------*/
554
 
555
/* This primitives manages a mutex in the system.
556
   The behavior of the functions is similar to the POSIX ones. */
557
 
558
 
559
/*+ Alloc a mutex descriptor +*/
560
int mutex_init(mutex_t *mutex, const mutexattr_t *attr);
561
 
562
/*+ Free a mutex descriptor  +*/
563
int mutex_destroy(mutex_t *mutex);
564
 
565
/*+ Block wait               +*/
566
int mutex_lock(mutex_t *mutex);
567
 
568
/*+ Non-block wait           +*/
569
int mutex_trylock(mutex_t *mutex);
570
 
571
/*+ unlock primitive +*/
572
int mutex_unlock(mutex_t *mutex);
573
 
574
/*---------------------------------------------------------------------*/
575
/* Condition variables                                                 */
576
/*---------------------------------------------------------------------*/
577
 
578
/*+ Initialization of the condition variable +*/
579
int cond_init(cond_t *cond);
580
 
581
/*+ free a condition variable descriptor +*/
582
int cond_destroy(cond_t *cond);
583
 
584
/*+ signal on a condition variable, it unlocks only one task +*/
585
int cond_signal(cond_t *cond);
586
 
587
/*+ broadcast on a condition variable, it unlocks all the blocked tasks +*/
588
int cond_broadcast(cond_t *cond);
589
 
590
/*+ wait on a condition variable +*/
591
int cond_wait(cond_t *cond, mutex_t *mutex);
592
 
593
/*+ wait on a condition variable (with timer) +*/
594
int cond_timedwait(cond_t *cond, mutex_t *mutex,
595
                   const struct timespec *abstime);
596
 
597
/*---------------------------------------------------------------------*/
598
/* Task specific data primitives                                       */
599
/*---------------------------------------------------------------------*/
600
 
601
/* they are similar to the POSIX standard */
602
 
603
int task_key_create(task_key_t *key, void (*destructor)(void *));
604
void *task_getspecific(task_key_t key);
605
int task_setspecific(task_key_t key, const void *value);
606
int task_key_delete(task_key_t key);
607
 
608
/*---------------------------------------------------------------------*/
609
/* Task cancellation handlers                                          */
610
/*---------------------------------------------------------------------*/
611
 
612
/*+ push the specified cancellation cleanup handler routine onto
613
    the cancellation cleanup stack
614
void task_cleanup_push(void (*routine)(void *), void *arg); +*/
615
#define task_cleanup_push(rtn,arg) { \
616
        struct _task_handler_rec __cleanup_handler, **__head; \
617
        __cleanup_handler.f = rtn; \
618
        __cleanup_handler.a = arg; \
619
        __head = task_getspecific(0); \
620
        __cleanup_handler.next = *__head; \
621
        *__head = &__cleanup_handler;
622
 
623
/*+
624
    removes the routine at the top of the cancellation cleanup stack
625
    of the calling thread
626
void task_cleanup_pop(int execute); +*/
627
#define task_cleanup_pop(ex) \
628
        *__head = __cleanup_handler.next; \
629
        if (ex) (*__cleanup_handler.f) (__cleanup_handler.a); \
630
}
631
 
632
#endif /* __FUNC_H__ */