1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
|
/* task-death.h - Task death notifications, interface.
Copyright (C) 2004 Free Software Foundation, Inc.
Written by Marcus Brinkmann <marcus@gnu.org>
This file is part of the GNU Hurd.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this program; if not, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
#ifndef _HURD_TASK_DEATH_H
#define _HURD_TASK_DEATH_H 1
#include <pthread.h>
/* We need to keep track of task deaths, because for IPC security we
hold task info capabilities which block reuse of the respective
task ID. At task death, we have to release these task info
capabilities so they become free for reuse. The task server
provides an interface to get the task IDs of all dead tasks to
which we still hold task info capabilities.
The following convention applies: Before you start allocating task
info capabilities, you must register a task death notify handler.
While you are requesting new task info capabilities and registering
it with your notify handler, you must take the
hurd_task_death_notify_lock to prevent task death notifications
from being processed (FIXME: Write a wrapper function for the task
server RPC to do this). You can release task info capabilities at
any time. However, if your notify handler is called, you MUST
release any task info capability you hold for that task ID. */
/* The type of a function callback that you can use to be informed
about task deaths. */
typedef void (task_death_notify_t) (void *hook, hurd_task_id_t task_id);
/* The struct you have to use to add your own notification
handler. */
struct hurd_task_death_notify_list_item
{
/* The following two members are internal. */
struct hurd_task_death_notify_list_item *next;
struct hurd_task_death_notify_list_item **prevp;
/* Your callback handler. */
task_death_notify_t *notify_handler;
/* This is passed as the first argument to your callback
handler. */
void *hook;
};
/* A lock that protects the linked list. It also is held when
callback handlers are called. */
extern pthread_mutex_t hurd_task_death_notify_lock;
/* The linked list of callback handlers. */
extern struct hurd_task_death_notify_list_item *hurd_task_death_notify_list;
/* Start task death notifications. Must be called once at startup. */
error_t hurd_task_death_notify_start (void);
/* Add the callback handler ITEM to the list. */
static inline void
hurd_task_death_notify_add (struct hurd_task_death_notify_list_item *item)
{
pthread_mutex_lock (&hurd_task_death_notify_lock);
if (hurd_task_death_notify_list)
hurd_task_death_notify_list->prevp = &item->next;
item->prevp = &hurd_task_death_notify_list;
item->next = hurd_task_death_notify_list;
hurd_task_death_notify_list = item;
pthread_mutex_unlock (&hurd_task_death_notify_lock);
};
/* Remove the callback handler ITEM from the list. */
static inline void
hurd_task_death_notify_remove (struct hurd_task_death_notify_list_item *item)
{
pthread_mutex_lock (&hurd_task_death_notify_lock);
if (item->next)
item->next->prevp = item->prevp;
*(item->prevp) = item->next;
pthread_mutex_unlock (&hurd_task_death_notify_lock);
};
/* Suspend processing task death notifications. Call this while
acquiring new task info capabilities and registering them with your
notify handler. */
static inline void
hurd_task_death_notify_suspend (void)
{
pthread_mutex_lock (&hurd_task_death_notify_lock);
}
/* Resumes processing task death notifications. Call this after
acquiring new task info capabilities and registering them with your
notify handler. */
static inline void
hurd_task_death_notify_resume (void)
{
pthread_mutex_unlock (&hurd_task_death_notify_lock);
}
#endif /* _HURD_TASK_DEATH_H */
|