219 |
/* The reference counter for this object. */ |
/* The reference counter for this object. */ |
220 |
uatomic32_t refs; |
uatomic32_t refs; |
221 |
|
|
222 |
/* The state of this object. If this is _HURD_CAP_STATE_GREEN, you |
/* The state of the capability object. |
223 |
can use the capability object. Otherwise, you should refrain |
|
224 |
from using it. You can sleep on the obj_state_cond condition in |
If STATE is _HURD_CAP_STATE_GREEN, you can use the capability |
225 |
the capability class until the state goes back to |
object. Otherwise, you must wait on the condition |
226 |
_HURD_CAP_STATE_GREEN again. |
CAP_CLASS->OBJ_COND for it return to _HURD_CAP_STATE_GREEN. |
227 |
|
|
228 |
If the state is _HURD_CAP_STATE_YELLOW, this means that there is |
If the state is _HURD_CAP_STATE_YELLOW, a thread wants the state |
229 |
some thread who wants the state to be _HURD_CAP_STATE_RED, and |
to be _HURD_CAP_STATE_RED (and it has canceled all other pending |
230 |
this thread canceled all other pending RPC threads on this |
RPC threads on this object). The last worker thread for this |
231 |
object. If you are the last worker thread for this capability |
capability object (other than the thread waiting for the |
232 |
object (except for the thread waiting for the condition to become |
condition to become _HURD_CAP_STATE_RED) must broadcast the |
233 |
_HURD_CAP_STATE_RED), you have to broadcast the obj_state_cond |
obj_state_cond condition. |
|
condition. |
|
234 |
|
|
235 |
Every worker thread that blocks on the capability object state |
Every worker thread that blocks on the capability object state |
236 |
until it reverts to _HURD_CAP_STATE_GREEN must perform a |
until it reverts to _HURD_CAP_STATE_GREEN must perform a |
258 |
/* Operations on capability classes. */ |
/* Operations on capability classes. */ |
259 |
|
|
260 |
/* Create a new capability class for objects with the size SIZE and |
/* Create a new capability class for objects with the size SIZE and |
261 |
alignment requirement ALIGNMENT. |
alignment requirement ALIGNMENT (which must be a power of 2). |
262 |
|
|
263 |
The callback OBJ_INIT is used whenever a capability object in this |
The callback OBJ_INIT is used whenever a capability object in this |
264 |
class is created. The callback OBJ_REINIT is used whenever a |
class is created. The callback OBJ_REINIT is used whenever a |
332 |
hurd_cap_obj_t *r_obj); |
hurd_cap_obj_t *r_obj); |
333 |
|
|
334 |
|
|
335 |
/* Get the size of the header, given the alignment requirement |
/* Get the offset of the user object following a capability. |
336 |
ALIGNMENT of the user object following it. */ |
ALIGNMENT is the alignment requirements of the user object as |
337 |
|
supplied to hurd_cap_class_init, hurd_cap_class_init_untyped, |
338 |
|
hurd_cap_class_create or hurd_cap_class_create_untyped. */ |
339 |
static inline size_t |
static inline size_t |
340 |
__attribute__((__always_inline__)) |
__attribute__((__always_inline__)) |
341 |
hurd_cap_obj_get_size (size_t alignment) |
hurd_cap_obj_user_offset (size_t alignment) |
342 |
{ |
{ |
343 |
size_t obj_size = sizeof (struct hurd_cap_obj); |
size_t offset = sizeof (struct hurd_cap_obj); |
344 |
size_t rest = sizeof (struct hurd_cap_obj) % alignment; |
size_t rest = sizeof (struct hurd_cap_obj) % alignment; |
345 |
|
|
346 |
if (rest) |
if (rest) |
347 |
obj_size += alignment - rest; |
offset += alignment - rest; |
348 |
|
|
349 |
return obj_size; |
return offset; |
350 |
} |
} |
351 |
|
|
352 |
|
|
361 |
{ |
{ |
362 |
uintptr_t obj_addr = (uintptr_t) obj; |
uintptr_t obj_addr = (uintptr_t) obj; |
363 |
|
|
364 |
obj_addr += hurd_cap_obj_get_size (alignment); |
obj_addr += hurd_cap_obj_user_offset (alignment); |
365 |
|
|
366 |
return (void *) obj_addr; |
return (void *) obj_addr; |
367 |
} |
} |
381 |
{ |
{ |
382 |
uintptr_t obj_addr = (uintptr_t) obj; |
uintptr_t obj_addr = (uintptr_t) obj; |
383 |
|
|
384 |
obj_addr -= hurd_cap_obj_get_size (alignment); |
obj_addr -= hurd_cap_obj_user_offset (alignment); |
385 |
|
|
386 |
return (hurd_cap_obj_t) obj_addr; |
return (hurd_cap_obj_t) obj_addr; |
387 |
} |
} |
410 |
pthread_mutex_lock (&obj->lock); |
pthread_mutex_lock (&obj->lock); |
411 |
} |
} |
412 |
|
|
|
|
|
413 |
/* Unlock the object OBJ, which must be locked. */ |
/* Unlock the object OBJ, which must be locked. */ |
414 |
static inline void |
static inline void |
415 |
hurd_cap_obj_unlock (hurd_cap_obj_t obj) |
hurd_cap_obj_unlock (hurd_cap_obj_t obj) |
418 |
} |
} |
419 |
|
|
420 |
|
|
421 |
/* Add a reference for the capability object OBJ. */ |
/* Add a reference to the capability object OBJ. */ |
422 |
static inline void |
static inline void |
423 |
hurd_cap_obj_ref (hurd_cap_obj_t obj) |
hurd_cap_obj_ref (hurd_cap_obj_t obj) |
424 |
{ |
{ |
426 |
} |
} |
427 |
|
|
428 |
|
|
429 |
/* Remove one reference for the capability object OBJ. Note that the |
/* Remove one reference for the capability object OBJ, which must be |
430 |
caller must have at least two references for this capability object |
locked. Note that the caller must have at least two references for |
431 |
when using this function. To release the last reference, |
this capability object when using this function. If this reference |
432 |
|
is potentially the last reference (i.e. the caller does not hold |
433 |
|
either directly or indirectly another reference to OBJ), |
434 |
hurd_cap_obj_drop must be used instead. */ |
hurd_cap_obj_drop must be used instead. */ |
435 |
static inline void |
static inline void |
436 |
hurd_cap_obj_rele (hurd_cap_obj_t obj) |
hurd_cap_obj_rele (hurd_cap_obj_t obj) |