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
 *   (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
 ------------
21
 CVS :        $Id: create.c,v 1.1.1.1 2002-03-29 14:12:51 pj Exp $
22
 
23
 File:        $File$
24
 Revision:    $Revision: 1.1.1.1 $
25
 Last update: $Date: 2002-03-29 14:12:51 $
26
 ------------
27
 
28
 This file contains:
29
 
30
 - the function that creates a task
31
 
32
---------------------------------------------------------------------
33
---------------------------------------------------------------------
34
---------------------------------------------------------------------
35
---------------------------------------------------------------------
36
IMPORTANT:
37
THIS FILE CURRENTLY IS NOT COMPILED BECAUSE IT IS SUBSTITUTED BY
38
THE GRPCREAT.C
39
IF YOU DON'T USE THE group_create FUNCTION, YOU CAN COMPILE THIS
40
FILE INSTEAD OF GRPCREAT.C
41
---------------------------------------------------------------------
42
---------------------------------------------------------------------
43
---------------------------------------------------------------------
44
---------------------------------------------------------------------
45
 
46
**/
47
 
48
/*
49
 * Copyright (C) 2000 Paolo Gai
50
 *
51
 * This program is free software; you can redistribute it and/or modify
52
 * it under the terms of the GNU General Public License as published by
53
 * the Free Software Foundation; either version 2 of the License, or
54
 * (at your option) any later version.
55
 *
56
 * This program is distributed in the hope that it will be useful,
57
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
58
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
59
 * GNU General Public License for more details.
60
 *
61
 * You should have received a copy of the GNU General Public License
62
 * along with this program; if not, write to the Free Software
63
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
64
 *
65
 */
66
 
67
#include <stdarg.h>
68
#include <ll/ll.h>
69
#include <ll/stdlib.h>
70
#include <ll/stdio.h>
71
#include <ll/string.h>
72
#include <kernel/config.h>
73
#include <kernel/model.h>
74
#include <kernel/const.h>
75
#include <sys/types.h>
76
#include <kernel/types.h>
77
#include <kernel/descr.h>
78
#include <errno.h>
79
#include <kernel/var.h>
80
#include <kernel/func.h>
81
#include <kernel/trace.h>
82
 
83
static DWORD unique_task_ID = 0;
84
 
85
/*+ Task create stub:
86
    when a task is created, the context is initialized to call this stub.
87
    Why??? for 2 reasons:
88
    - The signal delivery is done in the kern_context_load. When a task is
89
      created and activated but before the first dispatch, some signals
90
      could arrive... so the first thing a task have to do is to deliver
91
      pending signals...
92
    - When a task ends, it can return a value, so the value can be easily
93
      managed in the stub to implement task_join & co...
94
+*/
95
static void task_create_stub(void *arg)
96
{
97
  void *ret;
98
  kern_after_dispatch();
99
 
100
  ret = proc_table[exec_shadow].body(arg);
101
 
102
  kern_cli();
103
//  kern_printf("EXIT task %d, value %d\n",exec_shadow,ret);
104
  task_makefree(ret);
105
//  kern_printf("MAKEFREE return exec_shadow=%d task_counter=%d\n",exec_shadow,task_counter);
106
 
107
  ll_context_to(proc_table[exec_shadow].context);
108
}
109
 
110
/*+
111
  Allocate & fill a task descriptor; the task is not explicitely
112
  activated; you have to use the task_activate to do this
113
  Just set up the minimum necessary to make thing works well           +*/
114
 
115
PID task_createn(char *name,      /*+ the symbolic name of the task +*/
116
                 TASK (*body)(),  /*+ a pointer to the task body    +*/
117
                 TASK_MODEL *m,   /*+ the task model                +*/
118
                 ...)             /*+ the resources models, a list
119
                                     of RES_MODEL * terminated by NULL +*/
120
{
121
  PID i = NIL;     /* the task descriptor to fill... */
122
  CONTEXT c;       /* the context of the new task */
123
  BYTE *tos;       /* top of stack of the new task */
124
  LEVEL l;         /* used for searching the correct level of the task    */
125
  RLEVEL l_res;    /* used for searching the correct resource level ...   */
126
  RLEVEL l_rexit;  /* used for detaching a task from the resources levels */
127
  va_list rlist;   /* used for managing the resources models */
128
  RES_MODEL *r;    /*  "    "     "      "      "       "    */
129
  int j;           /* a counter */
130
  SYS_FLAGS f;     /* the flags to be restored at the end
131
                      (we must save them because the task_create can be
132
                       called at system initialization) */
133
 
134
  f = kern_fsave();
135
 
136
  printk("task_create\n");
137
 
138
  /* Get a free descriptor */
139
  for (;;) {
140
    i = q_getfirst(&freedesc);
141
 
142
    /* If no one is available abort the system */
143
    if (i == NIL) {
144
      errno = ENO_AVAIL_TASK;
145
      kern_frestore(f);
146
      return -1;
147
    }
148
 
149
    if (!(proc_table[i].control & WAIT_FOR_JOIN))
150
      break;
151
 
152
    proc_table[i].control |= DESCRIPTOR_DISCARDED;
153
  }
154
 
155
  /* Fill in the descriptor */
156
  proc_table[i].task_ID         = unique_task_ID++;
157
  proc_table[i].body            = body;
158
  strncpy(proc_table[i].name,name,19);
159
  proc_table[i].name[19]        = 0;
160
  proc_table[i].status          = SLEEP;    /* Task is not active when created */
161
  proc_table[i].pclass          = m->pclass & 0xFF00;
162
  proc_table[i].group           = m->group;
163
  proc_table[i].stacksize       = (m->stacksize == 0) ? STACK_SIZE : m->stacksize;
164
  proc_table[i].control         = m->control | KILL_DEFERRED | KILL_ENABLED;
165
  proc_table[i].frozen_activations = 0;
166
  proc_table[i].sigmask         = proc_table[exec_shadow].sigmask; /* mask inherit.*/
167
  proc_table[i].sigpending      = 0; /* No pending signal for new tasks*/
168
  proc_table[i].shadow          = i;
169
  proc_table[i].cleanup_stack   = NULL;
170
  proc_table[i].next            = proc_table[i].prev = NIL;
171
  proc_table[i].errnumber       = 0;        /* meaningless value */
172
 
173
  /* Fill jet info */
174
  proc_table[i].jet_tvalid      = 0;
175
  proc_table[i].jet_curr        = 0;
176
  proc_table[i].jet_max         = 0;
177
  proc_table[i].jet_sum         = 0;
178
  proc_table[i].jet_n           = 0;
179
  for (j=0; j<JET_TABLE_DIM; j++)
180
     proc_table[i].jet_table[j] = 0;
181
 
182
  proc_table[i].waiting_for_me  = NIL;
183
  proc_table[i].return_value    = NULL;
184
 
185
  proc_table[i].keys[0] = &proc_table[i].cleanup_stack;
186
  for (j=1; j<PTHREAD_KEYS_MAX; j++)
187
    proc_table[i].keys[j] = NULL;
188
 
189
  /* now, the task descriptor has some fields not initializated:
190
     - master_level   (initialized later, modified by l[]->task_create() )
191
     - task_level     (initialized later in this function)
192
     - context, stack (initialized at the end of this function)
193
     - request_time   (initialized when a request (activation) is issued)
194
     - additional stuff like priority & co. have to be init. only if used...)
195
     - delay_timer    (initialized in __kernel_init__ and mantained coherent
196
                       by the scheduling modules...)
197
     - guest_pclass   (set only in guest_create and used with guest task)
198
  */
199
 
200
  /* search for a level that can manage the task model */
201
  for (l=0; l<sched_levels; l++)
202
    if (level_table[l]->level_accept_task_model(l,m) >= 0)
203
      break;
204
  if (l == sched_levels) {
205
    /* no level can accept the task_model, exit!!! */
206
    proc_table[i].status = FREE;
207
    q_insertfirst(i,&freedesc);
208
    errno = ENO_AVAIL_SCHEDLEVEL;
209
    kern_frestore(f);
210
    return -1;
211
  }
212
 
213
  /* initialize task level and master level */
214
  proc_table[i].task_level = l;
215
 
216
  /* calls the task-oriented function task_create */
217
  if (level_table[l]->task_create(l,i,m) < 0) {
218
    /* an error occurred in the task_create */
219
    proc_table[i].status = FREE;
220
    q_insertfirst(i,&freedesc);
221
    errno = ETASK_CREATE;
222
    kern_frestore(f);
223
    return -1;
224
  }
225
 
226
  /* register all the resource models passed */
227
  va_start(rlist, m);
228
  for (;;) {
229
    r = va_arg(rlist,RES_MODEL *);
230
 
231
    if (!r) break;   /* all the resource models are managed */
232
 
233
    /* search for a level that can manage the resource model */
234
    for (l_res=0; l_res<res_levels; l_res++)
235
      if (resource_table[l_res]->level_accept_resource_model(l_res,r) >= 0) {
236
        resource_table[l_res]->res_register(l_res, i, r);
237
        break;
238
      }
239
    if (l_res == res_levels) {
240
      /* no level can accept the resource_model, exit!!! */
241
      /* detach the resources and the task */
242
      for (l_rexit=0; l_rexit<res_levels; l_rexit++)
243
        resource_table[l_rexit]->res_detach(l_rexit,i);
244
      level_table[l]->task_detach(l,i);
245
      proc_table[i].status = FREE;
246
      q_insertfirst(i,&freedesc);
247
      errno = ENO_AVAIL_RESLEVEL;
248
      kern_frestore(f);
249
      return -1;
250
    }
251
  }
252
  va_end(rlist);
253
 
254
  /* now we have to do the on-line guarantee of the system...
255
     The guarantee is made only if the task is inserted in a level that
256
     uses the guarantee (level_table[l]->level_guarantee != NULL)      */
257
  if (level_table[l]->level_guarantee)
258
    if (guarantee() < 0) {
259
      for (l_rexit=0; l_rexit<res_levels; l_rexit++)
260
        resource_table[l_rexit]->res_detach(l_rexit,i);
261
      level_table[l]->task_detach(l,i);
262
      proc_table[i].status = FREE;
263
      q_insertfirst(i,&freedesc);
264
      errno = ENO_GUARANTEE;
265
      kern_frestore(f);
266
      return -1;
267
    }
268
 
269
  /* Allocate a stack for the task, only if stackaddr != NULL */
270
  if (m->stackaddr) {
271
    tos = proc_table[i].stack = m->stackaddr;
272
    proc_table[i].control |= STACKADDR_SPECIFIED;
273
  }
274
  else {
275
    tos = proc_table[i].stack = (BYTE *) kern_alloc(proc_table[i].stacksize);
276
    if (proc_table[i].stack == NULL) {
277
      for (l_rexit=0; l_rexit<res_levels; l_rexit++)
278
        resource_table[l_rexit]->res_detach(l_rexit, i);
279
      level_table[l]->task_detach(l,i);
280
      proc_table[i].status = FREE;
281
      q_insertfirst(i,&freedesc);
282
      errno = ENO_AVAIL_STACK_MEM;
283
      kern_frestore(f);
284
      return -1;
285
    }
286
  }
287
 
288
  /* Set up the initial context */
289
  tos += proc_table[i].stacksize;
290
  c = kern_context_create(task_create_stub,tos,m->arg,NULL,m->control);
291
//  { extern CONTEXT global_context;
292
  if (!c) {// || c == global_context) {
293
/*    grx_close();
294
    { int i;
295
    for (i = 0; i<10000; i++)
296
    kern_printf("!!!\n"); } ll_abort(666); */
297
    kern_free(tos, proc_table[i].stacksize);
298
    for (l_rexit=0; l_rexit<res_levels; l_rexit++)
299
      resource_table[l_rexit]->res_detach(l_rexit, i);
300
    level_table[l]->task_detach(l,i);
301
    proc_table[i].status = FREE;
302
    q_insertfirst(i,&freedesc);
303
    errno = ENO_AVAIL_TSS;
304
    kern_frestore(f);
305
    return -1;
306
  }
307
//  }
308
  proc_table[i].context = c;
309
 
310
  /* Tracer stuff */
311
  trc_logevent(TRC_CREATE,&i);
312
  //kern_printf("[c%i %i]",i,proc_table[i].context);
313
 
314
  /* Count the task if it is an Application or System Task... */
315
  if (!(m->control & SYSTEM_TASK))
316
    task_counter++;
317
  else if (!(m->control & NO_KILL))
318
    system_counter++;
319
 
320
  kern_frestore(f);
321
 
322
  return(i);
323
}