Subversion Repositories shark

Rev

Rev 318 | Rev 327 | 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
 ------------
326 giacomo 21
 CVS :        $Id: kill.c,v 1.5 2003-11-12 17:28:20 giacomo Exp $
2 pj 22
 
23
 File:        $File$
326 giacomo 24
 Revision:    $Revision: 1.5 $
25
 Last update: $Date: 2003-11-12 17:28:20 $
2 pj 26
 ------------
27
 
28
 This file contains:
29
 
30
 - the function that kill a task (task_kill, group_kill)
31
 - the function that frees a task descriptor (makefree)
32
 - the task_abort
33
 
34
**/
35
 
36
/*
37
 * Copyright (C) 2000 Paolo Gai
38
 *
39
 * This program is free software; you can redistribute it and/or modify
40
 * it under the terms of the GNU General Public License as published by
41
 * the Free Software Foundation; either version 2 of the License, or
42
 * (at your option) any later version.
43
 *
44
 * This program is distributed in the hope that it will be useful,
45
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
46
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
47
 * GNU General Public License for more details.
48
 *
49
 * You should have received a copy of the GNU General Public License
50
 * along with this program; if not, write to the Free Software
51
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
52
 *
53
 */
54
 
55
#include <stdarg.h>
56
#include <ll/ll.h>
57
#include <ll/stdlib.h>
58
#include <ll/stdio.h>
59
#include <ll/string.h>
60
#include <kernel/config.h>
61
#include <kernel/model.h>
62
#include <kernel/const.h>
63
#include <sys/types.h>
64
#include <kernel/types.h>
65
#include <kernel/descr.h>
66
#include <errno.h>
67
#include <kernel/var.h>
68
#include <kernel/func.h>
69
#include <kernel/trace.h>
70
 
71
/*+ this structure contains the functions to be called to test if a
72
    task is blocked on a cancellation point +*/
73
static struct {
74
  int (*test)(PID p, void *arg);
75
  void *arg;
76
} cancellation_table[MAX_CANCPOINTS];
77
 
78
static int cancellation_points = 0;
79
 
80
void check_killed_async(void)
81
{
82
    if (proc_table[exec_shadow].control & KILL_ENABLED     &&
83
        !(proc_table[exec_shadow].control & KILL_DEFERRED) &&
84
        proc_table[exec_shadow].control & KILL_REQUEST        ) {
85
      task_makefree(TASK_CANCELED);
86
 
87
      ll_context_to(proc_table[exec_shadow].context);
88
      // never returns!!!
89
    }
90
}
91
 
92
/*+ This function register a cancellation point into the system.
93
    Be careful!!! no check are performed... +*/
94
void register_cancellation_point(int (*func)(PID p, void *arg), void *arg)
95
{
96
  cancellation_table[cancellation_points].test = func;
97
  cancellation_table[cancellation_points].arg = arg;
98
  cancellation_points++;
99
}
100
 
101
 
102
/*+
103
   This function frees the current task descriptor.
104
   It deletes the context and call the task_end and
105
   res_detach functions.
106
+*/
107
void task_makefree(void *ret)
108
{
109
    RLEVEL l;        /* used for managing the res_detach... */
110
    LEVEL lev;       /* for readableness */
111
    PID p;           /* used for controlling shadows */
112
    PID i;           /* used for readableness instead of exec_shadow */
113
 
114
    i = exec_shadow;
115
 
116
    /* first, contol if the task is joinable and someone is waiting for him
117
       This checks has to be done before  the shadow check (see below)
118
       because the task join uses the shadow field!!! */
119
    if (proc_table[i].control & TASK_JOINABLE) {
120
      proc_table[i].return_value = ret;
121
      proc_table[i].control |= WAIT_FOR_JOIN;
122
      if (proc_table[i].waiting_for_me != NIL) {
123
        /* someone is waiting for me... wake up him!!!
124
           Note that if the task woken up is killed by someone, the current
125
           task remain undetached; it is correct, as specified in 16.2.3 */
126
        register PID x;
127
        LEVEL l;
128
 
129
        x = proc_table[i].waiting_for_me;
130
        l = proc_table[x].task_level;
38 pj 131
        level_table[l]->public_unblock(l,x);
2 pj 132
 
133
        proc_table[x].shadow = x;
134
      }
135
    }
136
 
137
/*  {
138
   int xxx;
139
   kern_printf("(makefree ");
140
   for (xxx = 0; xxx<7; xxx++) kern_printf("p%d s%d|",xxx, proc_table[xxx].shadow);
141
   kern_printf(")\n");
142
  }*/
143
 
144
    /* we control if the task has someone with the shadow equal to
145
       the task being canceled... */
146
    for (p = 0; p<MAX_PROC; p++)
147
      if (p != i && proc_table[p].shadow == i) {
14 pj 148
        kern_raise(XINVALID_KILL_SHADOW,i);
2 pj 149
        return;
150
      }
151
 
152
    /* we call the cleanups functions */
153
    while (proc_table[i].cleanup_stack) {
154
      kern_sti();
155
      proc_table[i].cleanup_stack->f(proc_table[i].cleanup_stack->a);
156
      kern_cli();
157
      proc_table[i].cleanup_stack = proc_table[i].cleanup_stack->next;
158
    }
159
 
160
    /* call the thread-specific destructors */
161
    call_task_specific_data_destructors();
162
 
163
    /* Free the used context space */
164
    kern_context_delete(proc_table[i].context);
165
 
166
    /* tracer stuff */
167
    trc_logevent(TRC_DESTROY,&i);
168
    //kern_printf("[k%i]",i);
169
 
170
    /* Free the used stack area */
171
    /* Warning! we could be executing on the stack we are */
172
    /* going to destroy; this should cause no problem as  */
173
    /* the task_kill() cannot be interrupted & the memory */
174
    /* released can only be reassigned when we exit the   */
175
    /* primitive!                                         */
176
    if (!(proc_table[i].control & STACKADDR_SPECIFIED))
177
      kern_free(proc_table[i].stack,proc_table[i].stacksize);
178
 
179
 
180
    for (l=0; l<res_levels; l++)
181
      resource_table[l]->res_detach(l,i);
182
 
183
    lev = proc_table[i].task_level;
38 pj 184
    level_table[lev]->public_end(lev,i);
2 pj 185
 
186
    /* THIS ASSIGNMENT MUST STAY HERE!!!
187
       if we move it near the scheduler (after the counter checks)
188
       the kernel doesn't work, because:
189
       - if the task is the last one, a sys_end is called, but exec_shadow
190
         is != -1, so the sys_end calls the task_epilogue that reinsert
191
         the KILLED task into the ready queue!!!
192
    */
193
    exec = exec_shadow = -1;
194
 
195
    /* Decrement the Application task counter and end the system
196
       if necessary*/
197
    if (!(proc_table[i].control & SYSTEM_TASK)) {
198
      //kern_printf("Ûtask%dÛ",task_counter);
199
      task_counter--;
200
      if (!task_counter)
201
        sys_end();
202
    }
203
    else if (!(proc_table[i].control & NO_KILL)) {
204
      //kern_printf("Ûsyst%dÛ",system_counter);
205
      system_counter--;
206
      if (!system_counter)
207
        sys_end();
208
    }
209
 
326 giacomo 210
    //DON'T REMOVE !!! BUG IF EXEC_SHADOW = -1
211
    //kern_epilogue_macro();
2 pj 212
    /* there is no epilogue... */
38 pj 213
 
2 pj 214
    scheduler();
215
}
216
 
217
/*
218
  This primitive autokills the excuting task; it was used to avoid
219
  that returning from a task cause a jmp to an unpredictable location.
220
 
221
  Now it is obsolete, the task_create_stub do all the works.
222
 
223
  It is used by the Posix layer to implement pthread_exit
224
*/
225
void task_abort(void *returnvalue)
226
{
318 giacomo 227
    SYS_FLAGS f;
2 pj 228
 
318 giacomo 229
    f = kern_fsave();
230
 
2 pj 231
    task_makefree(returnvalue);
232
 
233
    ll_context_to(proc_table[exec_shadow].context);
234
}
235
 
236
/*+
237
  This primitive kills the i-th task, free the descriptor, and the
238
  memory for the stack
239
 
240
  look also at kern_init in kern.c!!!
241
+*/
242
int task_kill(PID i)
243
{
244
    int j;        /* a counter */
318 giacomo 245
    SYS_FLAGS f;
2 pj 246
 
318 giacomo 247
    f = kern_fsave();
2 pj 248
    if (proc_table[i].control & NO_KILL ||
249
        proc_table[i].status == FREE) {
14 pj 250
      errno = EINVALID_KILL;
318 giacomo 251
      kern_frestore(f);
2 pj 252
      return -1;
253
    }
254
 
255
    if (proc_table[i].control & KILL_REQUEST) {
256
      /* the task was already killed before... do nothing!!! */
318 giacomo 257
      kern_frestore(f);
2 pj 258
      return 0;
259
    }
260
 
261
    /* if cancellation is enabled and asyncronous (not deferred!),
262
       and it is a suicide, kill now, otherwise set the cancellation bit */
263
    if (i == exec_shadow &&
264
        proc_table[i].control & KILL_ENABLED &&
265
        !(proc_table[i].control & KILL_DEFERRED)) {
266
      task_makefree(TASK_CANCELED);
267
 
268
      ll_context_to(proc_table[exec_shadow].context);
269
      // never returns!!!
270
    }
271
 
272
    /* check if the task is blocked on a cancellation point */
273
    for (j=0; j<cancellation_points; j++)
274
       if (cancellation_table[j].test(i,cancellation_table[j].arg))
275
         break;
276
 
277
//    kern_printf("Û%d", proc_table[i].control);
278
 
279
    proc_table[i].control |= KILL_REQUEST;
280
 
318 giacomo 281
    kern_frestore(f);
2 pj 282
    return 0;
283
}
284
 
285
 
286
 
287
/* similar to task_kill */
288
int group_kill(WORD g)
289
{
290
    BYTE autokill;
291
    register PID i;
318 giacomo 292
    SYS_FLAGS f;
2 pj 293
 
294
    int j;        /* a counter */
295
 
296
    if (g == 0) {
14 pj 297
      errno = EINVALID_GROUP;
2 pj 298
      return -1;
299
    }
300
 
318 giacomo 301
    f = kern_fsave();
2 pj 302
 
303
    /* Detect suicide */
304
    autokill = (g == proc_table[exec].group);
305
 
306
    for (i=0 ; i <  MAX_PROC; i++) {
307
        if (proc_table[i].control & NO_KILL      ||
308
            proc_table[i].status == FREE         ||
309
            proc_table[i].control & KILL_REQUEST ||
310
            proc_table[i].group != g             )
311
          continue;
312
 
313
        /* if cancellation is enabled and asyncronous (not deferred!),
314
           and it is a suicide, kill now, otherwise set the cancellation bit */
315
        if (i == exec_shadow &&
316
            proc_table[i].control & KILL_ENABLED &&
317
            !(proc_table[i].control & KILL_DEFERRED)) {
318
          task_makefree(TASK_CANCELED);
319
          continue;
320
        }
321
 
322
        /* check if the task is blocked on a cancellation point */
323
        for (j=0; j<cancellation_points; j++)
324
           if (cancellation_table[j].test(i,cancellation_table[j].arg))
325
             break;
326
 
327
        proc_table[i].control |= KILL_REQUEST;
328
 
329
    }
330
 
331
    /* If we were killing ourselves we must switch context */
332
    /* without saving the actual one                       */
333
    if (autokill) {
334
      ll_context_to(proc_table[exec].context);
335
    }
336
    else
318 giacomo 337
      kern_frestore(f);
2 pj 338
 
339
    return 0;
340
}
341
 
342
 
343
/* this function is used into kernel_init to kill all the user tasks when
344
   the system goes to runlevel 2... */
345
void kill_user_tasks()
346
{
347
  PID k;
348
  int j;
349
 
350
  for (k=0; k<MAX_PROC; k++) {
351
    /* kill the task k!!! (see also task_kill in kill.c!!!) */
352
    if (proc_table[k].status == FREE ||
353
        proc_table[k].control & (KILL_REQUEST|NO_KILL|SYSTEM_TASK) )
354
      /* the task was already killed before... do nothing!!! */
355
      continue;
356
 
357
//    kern_printf("ÛKILLING %dÛ",k);
358
 
359
    /* check if the task is blocked on a cancellation point */
360
    for (j=0; j<cancellation_points; j++)
361
       if (cancellation_table[j].test(k,cancellation_table[j].arg))
362
         break;
363
 
364
    proc_table[k].control |= KILL_REQUEST;
365
  }
366
}