1 |
/* Copyright (C) 2003 Free Software Foundation, Inc. |
/* cap-user.c - User side of the capability implementation. |
2 |
|
Copyright (C) 2003 Free Software Foundation, Inc. |
3 |
Written by Marcus Brinkmann <marcus@gnu.org> |
Written by Marcus Brinkmann <marcus@gnu.org> |
4 |
|
|
5 |
This file is part of the GNU Hurd. |
This file is part of the GNU Hurd. |
29 |
#include "cap-intern.h" |
#include "cap-intern.h" |
30 |
|
|
31 |
|
|
32 |
|
/* This hash table maps server thread IDs to server connections. */ |
33 |
static struct hurd_ihash server_to_sconn |
static struct hurd_ihash server_to_sconn |
34 |
= HURD_IHASH_INITIALIZER (HURD_IHASH_NO_LOCP); |
= HURD_IHASH_INITIALIZER (HURD_IHASH_NO_LOCP); |
35 |
|
|
36 |
|
/* This lock protects SERVER_TO_SCONN. You can also lock server |
37 |
|
connection objects while holding this lock. */ |
38 |
static pthread_mutex_t server_to_sconn_lock = PTHREAD_MUTEX_INITIALIZER; |
static pthread_mutex_t server_to_sconn_lock = PTHREAD_MUTEX_INITIALIZER; |
39 |
|
|
40 |
|
|
41 |
/* Deallocate one reference for SCONN, which must be locked. |
/* Deallocate one reference for SCONN, which must be locked. |
42 |
SERVER_TO_SCONN_LOCK is not locked. Afterwards, SCONN is |
SERVER_TO_SCONN_LOCK is not locked. Afterwards, SCONN is unlocked |
43 |
unlocked. */ |
(if it still exists). */ |
44 |
void |
void |
45 |
_hurd_cap_sconn_dealloc (hurd_cap_sconn_t sconn) |
_hurd_cap_sconn_dealloc (hurd_cap_sconn_t sconn) |
46 |
{ |
{ |
76 |
pthread_mutex_unlock (&sconn->lock); |
pthread_mutex_unlock (&sconn->lock); |
77 |
pthread_mutex_destroy (&sconn->lock); |
pthread_mutex_destroy (&sconn->lock); |
78 |
hurd_ihash_destroy (&sconn->id_to_cap); |
hurd_ihash_destroy (&sconn->id_to_cap); |
79 |
hurd_cap_deallocate (sconn->server_task_id); |
if (sconn->server_task_id) |
80 |
|
hurd_cap_deallocate (sconn->server_task_id); |
81 |
free (sconn); |
free (sconn); |
82 |
} |
} |
83 |
|
|
101 |
|
|
102 |
/* Enter a new send capability provided by the server SERVER_THREAD |
/* Enter a new send capability provided by the server SERVER_THREAD |
103 |
(with the task ID reference SERVER_TASK_ID) and the cap ID SCID. |
(with the task ID reference SERVER_TASK_ID) and the cap ID SCID. |
104 |
The SERVER_TASK_ID reference is _not_ consumed but copied if |
If successful, the locked capability is returned with one |
105 |
necessary. If successful, the locked capability is returned with |
(additional) reference in CAP. The server connection and |
|
one (additional) reference in CAP. The server connection and |
|
106 |
capability object are created if necessary. */ |
capability object are created if necessary. */ |
107 |
error_t |
error_t |
108 |
_hurd_cap_sconn_enter (l4_thread_id_t server_thread, uint32_t scid, |
_hurd_cap_sconn_enter (l4_thread_id_t server_thread, uint32_t scid, |
109 |
task_id_t server_task_id, hurd_cap_t *cap) |
hurd_cap_t *cap) |
110 |
{ |
{ |
111 |
hurd_cap_sconn_t sconn; |
hurd_cap_sconn_t sconn; |
112 |
int sconn_created = 0; |
int sconn_created = 0; |
116 |
if (!sconn) |
if (!sconn) |
117 |
{ |
{ |
118 |
error_t err; |
error_t err; |
119 |
|
hurd_task_id_t server_task = hurd_task_id_from_thread_id (server_thread); |
120 |
|
hurd_task_id_t taskserver_task; |
121 |
|
|
122 |
|
taskserver_task = hurd_task_id_from_thread_id |
123 |
|
(hurd_cap_get_thread_id (hurd_task_self())); |
124 |
|
|
125 |
sconn = malloc (sizeof (*sconn)); |
sconn = malloc (sizeof (*sconn)); |
126 |
if (!sconn) |
if (!sconn) |
135 |
pthread_mutex_unlock (&server_to_sconn_lock); |
pthread_mutex_unlock (&server_to_sconn_lock); |
136 |
return errno; |
return errno; |
137 |
} |
} |
138 |
hurd_ihash_init (&sconn->id_to_cap); |
|
139 |
|
if (server_task != taskserver_task) |
140 |
|
{ |
141 |
|
err = hurd_task_info_create (hurd_task_self (), |
142 |
|
server_task, |
143 |
|
&sconn->server_task_id); |
144 |
|
if (err) |
145 |
|
{ |
146 |
|
pthread_mutex_destroy (&sconn->lock); |
147 |
|
free (sconn); |
148 |
|
pthread_mutex_unlock (&server_to_sconn_lock); |
149 |
|
return errno; |
150 |
|
} |
151 |
|
} |
152 |
|
else |
153 |
|
sconn->server_task_id = 0; |
154 |
|
|
155 |
|
hurd_ihash_init (&sconn->id_to_cap); |
156 |
sconn->server_thread = server_thread; |
sconn->server_thread = server_thread; |
|
sconn->server_task_id = server_task_id; |
|
157 |
sconn->refs = 0; |
sconn->refs = 0; |
158 |
|
|
159 |
/* Enter the new server connection object. */ |
/* Enter the new server connection object. */ |
166 |
pthread_mutex_unlock (&server_to_sconn_lock); |
pthread_mutex_unlock (&server_to_sconn_lock); |
167 |
return errno; |
return errno; |
168 |
} |
} |
|
|
|
|
/* FIXME: This could, theoretically, overflow. */ |
|
|
hurd_cap_mod_refs (server_task_id, +1); |
|
169 |
} |
} |
170 |
pthread_mutex_lock (&sconn->lock); |
pthread_mutex_lock (&sconn->lock); |
171 |
sconn->refs++; |
sconn->refs++; |