summaryrefslogtreecommitdiff
path: root/libhurd-cap-server
diff options
context:
space:
mode:
Diffstat (limited to 'libhurd-cap-server')
-rw-r--r--libhurd-cap-server/ChangeLog499
-rw-r--r--libhurd-cap-server/Makefile.am41
-rw-r--r--libhurd-cap-server/README185
-rw-r--r--libhurd-cap-server/bucket-create.c176
-rw-r--r--libhurd-cap-server/bucket-free.c47
-rw-r--r--libhurd-cap-server/bucket-inhibit.c142
-rw-r--r--libhurd-cap-server/bucket-inject.c58
-rw-r--r--libhurd-cap-server/bucket-manage-mt.c1116
-rw-r--r--libhurd-cap-server/bucket-worker-alloc.c51
-rw-r--r--libhurd-cap-server/cap-server-intern.h599
-rw-r--r--libhurd-cap-server/cap-server.h573
-rw-r--r--libhurd-cap-server/class-alloc.c64
-rw-r--r--libhurd-cap-server/class-create.c75
-rw-r--r--libhurd-cap-server/class-destroy.c58
-rw-r--r--libhurd-cap-server/class-free.c48
-rw-r--r--libhurd-cap-server/class-inhibit.c114
-rw-r--r--libhurd-cap-server/class-init.c180
-rw-r--r--libhurd-cap-server/client-create.c213
-rw-r--r--libhurd-cap-server/client-inhibit.c157
-rw-r--r--libhurd-cap-server/client-release.c192
-rw-r--r--libhurd-cap-server/ctx-cap-use.c278
-rw-r--r--libhurd-cap-server/headers.m413
-rw-r--r--libhurd-cap-server/obj-copy-out.c121
-rw-r--r--libhurd-cap-server/obj-dealloc.c50
-rw-r--r--libhurd-cap-server/obj-drop.c36
-rw-r--r--libhurd-cap-server/obj-entry-space.c52
-rw-r--r--libhurd-cap-server/obj-inhibit.c131
-rw-r--r--libhurd-cap-server/table.c96
-rw-r--r--libhurd-cap-server/table.h207
-rw-r--r--libhurd-cap-server/task-death.c77
-rw-r--r--libhurd-cap-server/task-death.h123
31 files changed, 0 insertions, 5772 deletions
diff --git a/libhurd-cap-server/ChangeLog b/libhurd-cap-server/ChangeLog
deleted file mode 100644
index db21a71..0000000
--- a/libhurd-cap-server/ChangeLog
+++ /dev/null
@@ -1,499 +0,0 @@
-2005-03-08 Neal H. Walfield <neal@gnu.org>
-
- * Makefile.am (libhurd_cap_server_a_SOURCES): Add ctx-cap-use.c.
- * cap-server.h (struct hurd_cap_rpc_context): Add member HANDLE.
- (struct hurd_cap_ctx_cap_use): New forward.
- (hurd_cap_ctx_size): New declaration.
- (hurd_cap_ctx_start_cap_use): New declaration.
- (hurd_cap_ctx_end_cap_use): New declaration.
- * cap-server-intern.h (struct hurd_cap_ctx_cap_use): New
- structure.
- * bucket-manage-mt.c (manage_demuxer): Save capability handle in
- CTX->handle.
- * ctx-cap-use.c: New file.
-
-2005-01-12 Neal H. Walfield <neal@gnu.org>
-
- * class-init.c (hurd_cap_class_init_untyped): Fix assert.
- * bucket-manage-mt.c (manage_mt_worker): Likewise.
-
-2005-01-10 Bas Wijnen <shevek@fmf.nl>
-
- * README (TODO): Fix spelling errors.
-
-2005-01-07 Neal H. Walfield <neal@gnu.org>
-
- * class-init.c (hurd_cap_class_init_untyped): Supply the
- allocate_buffer and deallocate_buffer arguments to
- hurd_slab_create to conform with the new semantics.
- * obj-entry-space.c (_hurd_cap_obj_entry_space): Likewise for
- HURD_SLAB_SPACE_INITIALIZER.
- * client-create.c (_hurd_cap_client_space): Likewise.
-
-2004-12-01 Neal H. Walfield <neal@gnu.org>
-
- * cap-server-intern.h (struct _hurd_cap_client): Fold the struct
- _hurd_cap_client_entry into the struct _hurd_cap_client.
- * bucket-create.c (_hurd_cap_client_death): Change all uses of
- _hurd_cap_client_entry_t to use the merged _hurd_cap_client_t.
- (hurd_cap_bucket_create): Likewise.
- * bucket-manage-mt.c (lookup_client): Likewise.
- * client-create.c (_hurd_cap_client_create): Likewise.
- * client-release.c (_hurd_cap_client_release): Likewise.
-
-2004-12-01 Neal H. Walfield <neal@gnu.org>
-
- * cap-server-intern.h (_HURD_CAP_CLIENT_ID_BITS): Move from
- ../hurd/types.h. Prepend underscore and update names in
- definition as needed.
- (_HURD_CAP_ID_BITS): Likewise.
- (_HURD_CAP_CLIENT_ID_MASK): Likewise.
- (_HURD_CAP_ID_MASK): Likewise.
- (_hurd_cap_id_t): Likewise.
- (_hurd_cap_client_id_t): Likewise.
- (_hurd_cap_client_id): Likewise.
- (_hurd_cap_id): Likewise.
- (_hurd_cap_handle_make): Likewise.
-
- * bucket-inject.c (hurd_cap_bucket_inject): Update CAP_ID's type.
- * bucket-manage-mt.c (lookup_client): Likewise for CLIENT_ID.
- * cap-server-intern.h (struct _hurd_cap_obj_entry): Likewise for
- ID.
- (_hurd_cap_obj_copy_out): Likewise for CLIENT.
- (struct _hurd_cap_client): Likewise for ID.
- (_hurd_cap_client_release): Likewise for IDX.
- * client-release.c (_hurd_cap_client_release): Likewise for IDX.
- * obj-copy-out.c (_hurd_cap_obj_copy_out): Likewise for CLIENT.
-
-2004-12-01 Marcus Brinkmann <marcus@gnu.org>
-
- * client-create.c (_hurd_cap_client_constructor): Do not
- initialize CLIENT->caps table here.
- (_hurd_cap_client_alloc): Do not initialize CLIENT->lock,
- CLIENT->state or CLIENT->pending_rpcs here.
- Reported by Neal Walfield <neal@gnu.org>.
-
- * bucket-manage-mt.c (manage_demuxer): Rework the logic that tries
- to wait until the client becomes inhibited.
- Reported by Neal Walfield <neal@gnu.org>.
-
-2004-11-30 Neal H. Walfield <neal@gnu.org>
-
- * cap-server.h: Improve comments.
- (hurd_cap_class_create_untyped): Tighten alignment restrictions:
- ALIGNMENT must be a power of 2.
- * class-init.c (hurd_cap_class_init_untyped): Calculate best
- alignment.
-
- * cap-server.h (hurd_cap_obj_get_size): Renamed to ...
- (hurd_cap_obj_user_offset): ... this.
- (hurd_cap_obj_to_user_untyped): Call hurd_cap_obj_user_offset, not
- hurd_cap_obj_get_size.
- (hurd_cap_obj_from_user_untyped): Likewise.
- * class-init.c (hurd_cap_class_init_untyped): Likewise.
-
- * class-create.c: Improve comments.
- * obj-copy-out.c: Likewise.
-
-2004-11-30 Neal H. Walfield <neal@gnu.org>
-
- * cap-server-intern.h (_hurd_cap_obj_drop): Reverse faulty logic.
-
-2004-11-30 Neal H. Walfield <neal@gnu.org>
-
- * bucket-manage-mt.c (manage_mt_get_next_worker): If
- pthread_create_from_l4_tid_np fails, return WORKER to pthread's
- available thread pool.
- (worker_alloc_async): Likewise.
- (hurd_cap_bucket_manage_mt): Likewise.
-
-2004-11-30 Neal H. Walfield <neal@gnu.org>
-
- * bucket-manage-mt.c: Include <compiler.h>.
- (manage_mt_worker): Use EXPECT_TRUE and EXPECT_FALSE rather than
- __builtin_expect. Comment fixes.
- (manage_mt_get_next_worker): Likewise.
- (hurd_cap_bucket_manage_mt): Likewise.
- * cap-server-intern.h: Include <compiler.h>.
- (_hurd_cap_obj_drop): Use EXPECT_FALSE rather than
- __builtin_expect.
- (struct _hurd_cap_bucket): Comment fix.
- * client-release.c: Include <compiler.h>.
- (_hurd_cap_client_release): Use EXPECT_TRUE rather than
- __builtin_expect.
-
-2004-11-30 Neal H. Walfield <neal@gnu.org>
-
- * bucket-create.c (_hurd_cap_client_death): Comparisons use ==,
- not =. Fix it.
-
-2004-11-29 Neal H. Walfield <neal@gnu.org>
-
- * client-create.c (_hurd_cap_client_create): Deallocate the
- gratuitous _hurd_cap_client_t, not the one we want to use.
-
-2004-11-01 Marcus Brinkmann <marcus@gnu.org>
-
- * cap-server.h (hurd_cap_class_create): Rename to ...
- (hurd_cap_class_create_untyped): ... this.
- (hurd_cap_class_create): New macro.
- (hurd_cap_class_init): Rename to ...
- (hurd_cap_class_init_untyped): ... this.
- (hurd_cap_class_init): New macro.
- (hurd_cap_get_obj_size): New inline function.
- (hurd_cap_obj_to_user_untyped, hurd_cap_obj_from_user_untyped):
- New inline function.
- (hurd_cap_obj_to_user, hurd_cap_obj_from_user): New macro.
- * class-alloc.c (hurd_cap_class_alloc): New variable NEW_OBJ, use
- it as a temporary placeholder.
- * class-create.c (hurd_cap_class_create): Rename to ...
- (hurd_cap_class_create_untyped): ... this.
- Use hurd_cap_class_init_untyped.
- * class-init.c (hurd_cap_class_init): Rename to ...
- (hurd_cap_class_init_untyped): ... this.
- Add the size of struct hurd_cap_obj to SIZE.
- * client-create.c (_hurd_cap_client_alloc): New variable
- NEW_CLIENT, use it as a temporary placeholder.
- * obj-copy-out.c (_hurd_cap_obj_copy_out): New variable NEW_ENTRY,
- use it as a temporary placeholder.
-
- * bucket-inhibit.c (hurd_cap_bucket_end): Return something.
-
- * cap-server-intern.h (_hurd_cap_bucket_cond_check): Fix
- assignemnt.
- * table.h (hurd_table_lookup): Remove unused variable ERR.
- * table.c (hurd_table_enter): Likewise.
- * bucket-manage-mt.c (manage_demuxer): Remove unused variable
- FROM.
- (manage_mt_worker): Remove unused variable DEMUXED.
- (worker_alloc_async): Remove unused variable WORKER_ITEM. Fix
- assignments.
- * client-release.c (_hurd_cap_client_dealloc): Remove unused
- variables DONE, CURRENT_IDX.
- (_hurd_cap_client_release): Remove unused variable FOUND.
-
-2004-10-29 Marcus Brinkmann <marcus@gnu.org>
-
- * cap-server.h: Include <atomic.h>.
- (struct hurd_cap_obj): Change type of member refs
- from unsigned int to uatomic32_t.
- (hurd_cap_obj_ref): Use atomic_increment().
- (hurd_cap_obj_rele): Use atomic_decrement().
- * cap-server-intern.h (_hurd_cap_obj_drop): Remove unused variable
- cap_class. Use atomic_decrement_and_test.
- * obj-dealloc.c (_hurd_cap_obj_dealloc): Assert that OBJ->refs is
- 0, not 1. Do not unlock the object.
-
-2004-10-25 Marcus Brinkmann <marcus@gnu.org>
-
- * Makefile.am (libhurd_cap_server_a_SOURCES): Add
- bucket-worker-alloc.c.
- * bucket-worker-alloc.c: New file.
- * bucket-create.c (hurd_cap_bucket_create): Initialize
- BUCKET->worker_alloc_sync and BUCKET->worker_alloc_state.
- * cap-server-intern.h (struct _hurd_cap_bucket): New members
- worker_alloc_async and worker_alloc.
- * cap-server.h (hurd_cap_bucket_worker_alloc): New prototype.
- * bucket-manage-mt.c (hurd_cap_bucket_manage_mt): Move
- initialization of acceptor and xfer timeouts to just before the
- IPC (repeat it for every IPC). Set xfer timeout to all zero. Do
- not pay attention to BUCKET->free_worker after cancelling the
- current worker thread at shutdown. Create a worker allocation
- thread if requested, and shut it down before terminating.
- (manage_mt_worker): Take a new argument, ASYNC. If it is set, add
- worker thread to free list at startup, and use a timeout for the
- first wait.
- (manage_mt_worker_async, manage_mt_worker_sync): New wrapper
- functions.
- (worker_alloc_async): New function.
- (manage_mt_get_next_worker):
-
-2004-10-23 Marcus Brinkmann <marcus@gnu.org>
-
- * bucket-manage-mt.c: Include <l4.h>.
- (l4_xreceive, l4_xreceive_timeout): New macros.
- (manage_mt_worker): Use l4_xreceive and l4_xreceive_timeout
- instead l4_wait and l4_wait_timeout.
-
-2004-10-19 Marcus Brinkmann <marcus@gnu.org>
-
- * client-inhibit.c (_hurd_cap_client_resume): Lock CLIENT->lock,
- not BUCKET->lock.
- * obj-inhibit.c (hurd_cap_obj_resume): Lock OBJ->lock, not
- CAP_CLASS->lock.
-
-2004-10-07 Marcus Brinkmann <marcus@gnu.org>
-
- * bucket-manage-mt.c (reply_err): Don't set propagation flag.
- (manage_mt_worker): Clear the propagation flag.
-
-2004-08-02 Peter Bruin <pjbruin@dds.nl>
-
- * cap-server-intern.h (_hurd_cap_bucket_cond_check): Call
- _hurd_cap_bucket_cond_busy instead taking its address.
-
-2004-04-12 Marcus Brinkmann <marcus@gnu.org>
-
- * bucket-manage-mt.c (manage_mt_worker): Set CTX.obj to NULL
- before calling demuxer. If later on CTX.obj is not NULL, call
- manage_demuxer_cleanup after sending the reply message. Set
- propagation flag in message tag.
- (manage_demuxer): Do not release OBJ lock before calling the
- demuxer, do not acquire and release OBJ lock afterwards. Instead,
- acquire a reference to OBJ.
- (reply_err): Set propagation flag in message tag.
-
-2004-04-11 Marco Gerards <metgerards@student.han.nl>
-
- * table.c (hurd_table_init): Return an error code.
-
-2004-04-10 Marcus Brinkmann <marcus@gnu.org>
-
- * bucket-manage-mt.c (manage_mt_worker): Use
- _hurd_cap_list_item_dequeued to set current_worker_is_us.
-
-2004-04-09 Marcus Brinkmann <marcus@gnu.org>
-
- * cap-server.h (hurd_cap_bucket_inject): Change hurd_cap_t to
- hurd_cap_handle_t in R_CAP argument type.
- * bucket-manage-mt.c (manage_demuxer): Likewise.
- * bucket-inject.c (hurd_cap_bucket_inject): Likewise. Use
- hurd_cap_handle_make instead hurd_cap_make.
-
- * obj-copy-out.c (_hurd_cap_obj_copy_out): Set *R_ID after adding
- element.
- * bucket-inject.c (hurd_cap_bucket_inject): Set *R_CAP and return 0.
-
-2004-04-08 Marcus Brinkmann <marcus@gnu.org>
-
- * bucket-inject.c, obj-copy-out.c: New files.
- * Makefile.am (libhurd_cap_server_a_SOURCES): Add bucket-inject.c
- and obj-copy-out.c
- * bucket-create.c (hurd_cap_bucket_create): Initialize members
- is_managed, nr_caps, waiting_rpcs of BUCKET. Set R_BUCKET.
- * cap-server-intern.h (_hurd_cap_client_dealloc): Add new argument
- BUCKET to prototype.
- (struct hurd_cap_client): Remove declaration.
- (struct _hurd_cap_list_item): Add new member tid. Change type for
- member client to _hurd_cap_client_t.
- (_hurd_cap_list_item_add, _hurd_cap_list_item_remove,
- _hurd_cap_list_item_dequeued): New inline functions.
- (struct _hurd_cap_obj_entry): Rename member IDX to ID.
- (_hurd_cap_obj_copy_out): New prototype.
- (_hurd_cap_client_create): Remove argument R_IDX from prototype.
- (struct _hurd_cap_bucket): Add new members MANAGER, IS_MANAGED,
- IS_MANAGER_WAITING, NR_CAPS, WAITING_RPCS, and FREE_WORKER.
- (_hurd_cap_client_t): Type definition moved to ...
- * cap-server.h (_hurd_cap_client_t): Here.
- (struct _hurd_cap_client_t): New declaration.
- (struct hurd_cap_rpc_context): Define it.
- (hurd_cap_class_demux_t): Renamed to ...
- (hurd_cap_class_demuxer_t): ... this.
- (hurd_cap_class_create, hurd_cap_class_init): Use new type for demuxer
- argument in prototype.
- (hurd_cap_bucket_inject): New prototype.
- * cap-server.h: Include <hurd/types.h>
- * class-create (hurd_cap_class_create): Use new type for demuxer
- argument. Set R_CLASS.
- * class-init (hurd_cap_class_init): Use new type for demuxer argument.
- * client-release.c (_hurd_cap_client_dealloc): Take new argument
- BUCKET. New local variable NR_CAPS. Keep track of number of
- capabilities removed. Update BUCKET->nr_caps before return.
- (_hurd_cap_client_release): Pass new argument BUCKET to
- _hurd_cap_client_release.
- * client-create.c (_hurd_cap_client_create): Remove argument
- R_IDX. Consequently, do not set R_IDX anymore. Set R_CLIENT.
- Pass new argument BUCKET to _hurd_cap_client_dealloc.
- * bucket-inhibit.c (hurd_cap_bucket_end): Check BUCKET->nr_caps if
- FORCE flag is not set. Cancel the manager thread if needed.
- (_hurd_cap_bucket_cond_busy): Move to ...
- * cap-server-intern.h (_hurd_cap_bucket_cond_busy): ... here.
- Add attribute always-inline.
- (_hurd_cap_bucket_cond_check): New inline function.
- * client-inhibit.c (_hurd_cap_client_cond_busy): Move to ...
- * cap-server-intern.h (_hurd_cap_client_cond_busy): ... here.
- Add attribute always-inline.
- (_hurd_cap_client_cond_check): New inline function.
- * class-inhibit.c (_hurd_cap_class_cond_busy): Move to ...
- * cap-server-intern.h (_hurd_cap_class_cond_busy): ... here.
- Add attribute always-inline.
- (_hurd_cap_class_cond_check): New inline function.
- * obj-inhibit.c (_hurd_cap_obj_cond_busy): Move to ...
- * cap-server-intern.h (_hurd_cap_obj_cond_busy): ... here.
- Add attribute always-inline.
- (_hurd_cap_obj_cond_check): New inline function.
-
-2004-04-01 Marcus Brinkmann <marcus@gnu.org>
-
- * Makefile.am (libhurd_cap_server_a_SOURCES): Remove bucket-add.c,
- bucket-remove.c.
- * bucket-add.c, bucket-remove.c: Files removed.
- * cap-server.h (hurd_cap_bucket_add, hurd_cap_bucket_remove):
- Remove prototypes.
- * cap-server-intern.h (struct _hurd_cap_class_entry): Removed.
- (_hurd_cap_class_entry_t): Removed.
- (struct _hurd_cap_bucket): Remove member classes.
- * bucket-create.c (hurd_cap_bucket_create): Do not initialize
- deleted member classes.
- * bucket-free.c (hurd_cap_bucket_free): Do not destroy deleted
- member classes.
-
-2004-03-26 Marcus Brinkmann <marcus@gnu.org>
-
- * bucket-add.c, bucket-create.c, bucket-free.c, bucket-inhibit.c,
- bucket-manage-mt.c, bucket-remove.c, cap-server-intern.h,
- class-free.c, class-init.c, obj-dealloc.c, obj-drop.c,
- obj-entry-space.c: New files.
- * Makefile.am (includehurd_HEADERS): Move table.h and task-death.h
- to ...
- (libhurd_cap_server_a_SOURCES): ... here. Add
- cap-server-intern.h, class-init.c, class-free.c, obj-dealloc.c,
- obj-drop.c, obj-entry-space.c, bucket-create.c, bucket-free.c,
- bucket-add.c, bucket-remove.c, bucket-inhibit.c,
- bucket-manage-mt.c. Remove class-dealloc.c.
- * headers.m4: Remove table.h and task-death.h.
- * cap-server.h: Include <stdbool.h>, do not include <assert.h>,
- <limits.h>, <hurd/types.h>, <hurd/slab.h>, <hurd/table.h>,
- <hurd/ihash.h> and <hurd/task-death.h>.
- (hurd_cond_wait, struct _hurd_cap_list_item,
- _hurd_cap_list_item_t, _hurd_cap_list_item_add,
- _hurd_cap_list_item_remove, struct _hurd_cap_entry,
- _hurd_cap_entry_t, struct hurd_cap_client, hurd_cap_client_t,
- struct _hurd_cap_client_entry, _hurd_cap_client_entry_t,
- _hurd_cap_class_dealloc, _hurd_cap_client_create,
- hurd_cap_client_lookup, _hurd_cap_client_dealloc,
- hurd_cap_client_inhibit, hurd_cap_client_resume,
- _hurd_cap_client_end): Removed.
- (hurd_cap_rpc_context): New declaration.
- (hurd_cap_class_demux_t): New dummy type (for now).
- (struct hurd_cap_class): Remove members OBJ_SIZE, CLIENT_SLAB,
- CLIENT_COND, CLIENT_COND_LOCK, CLIENTS, CLIENTS_REVERSE,
- CLIENT_THREADS and CLIENT_DEATH_NOTIFY. Change type of OBJ_SLAB
- to struct hurd_slab_space and rename it to OBJ_SPACE. Add member
- DEMUXER. Change type of member STATE to _hurd_cap_state_t.
- (struct hurd_cap_obj): Add member CAP_CLASS. Change type of
- member STATE to _hurd_cap_state_t.
- (hurd_cap_class_create): Add arguments alignment and demuxer to
- prototype.
- (hurd_cap_class_init): Likewise.
- (hurd_cap_class_free): New prototype.
- (_hurd_cap_class_destroy): Rename to ...
- (hurd_cap_class_destroy): ... this.
- (hurd_cap_obj_lock, hurd_cap_obj_unlock, hurd_cap_obj_ref,
- hurd_cap_obj_rele, hurd_cap_obj_drop): Remove CAP_CLASS argument.
- (hurd_cap_obj_drop): Only declare prototype here.
- (struct _hurd_cap_bucket): New forward declaration.
- (hurd_cap_bucket_t): New typedef.
- (hurd_cap_bucket_create, hurd_cap_bucket_free,
- hurd_cap_bucket_add, hurd_cap_bucket_remove,
- hurd_cap_bucket_manage_mt, hurd_cap_bucket_inhibit,
- hurd_cap_bucket_resume, hurd_cap_bucket_end): New prototypes.
- * class-alloc.c, class-create.c, class-destroy.c, class-inhibit.c,
- client-create.c, client-inhibit.c, client-release.c,
- obj-inhibit.c: Change the callers to take into account the above
- changes.
-
-2004-03-25 Marcus Brinkmann <marcus@gnu.org>
-
- * Makefile.am (libhurd_cap_server_a_SOURCES): Add class-inhibit.c,
- client-create.c, client-release.c, client-inhibit.c, and
- obj-inhibit.c.
- * README, class-inhibit.c, client-create.c, client-release.c,
- client-inhibit.c, obj-inhibit.c: New files.
- * cap-server.h: Protect inclusion with _HURD_CAP_SERVER_H.
- Include <hurd/types.h>, <hurd/table.h>, <hurd/ihash.h> and
- <hurd/task-death.h>.
- (hurd_cond_wait): Define to pthread_cond_wait for now.
- (struct _hurd_cap_list_item): New struct.
- (_hurd_cap_list_item_t): New typedef.
- (_hurd_cap_list_item_add, _hurd_cap_list_item_remove): New inline
- functions.
- (enum _hurd_cap_state): New enum.
- (struct _hurd_cap_obj): Add members STATE, PENDING_RPCS,
- COND_WAITER, and CLIENTS.
- (hurd_cap_obj_data): Removed.
- (struct _hurd_cap_entry): New struct.
- (_hurd_cap_entry_t): New type.
- (struct hurd_cap_client): New struct.
- (hurd_cap_client_t): New type.
- (struct _hurd_cap_client_entry): New struct.
- (_hurd_cap_client_entry_t): New type.
- (struct hurd_cap_class): Rename member SLAB to OBJ_SLAB. Add new
- members OBJ_COND, OBJ_COND_LOCK, CLIENT_SLAB, CLIENT_COND,
- CLIENT_COND_LOCK, CLIENT_DEATH_NOTIFY, LOCK, CLIENTS,
- CLIENTS_REVERSE, STATE, COND, COND_WAITER and PENDING_RPCS.
- (hurd_cap_class_init, _hurd_cap_class_destroy): New prototypes.
- (hurd_cap_class_dealloc): Rename prototype to ...
- (_hurd_cap_class_dealloc): ... this.
- (hurd_cap_obj_lock, hurd_cap_obj_unlock): Change return type to
- void.
- (hurd_cap_obj_drop): Call _hurd_cap_class_dealloc (not
- hurd_cap_class_dealloc).
- (_hurd_cap_client_create, _hurd_cap_client_dealloc,
- _hurd_cap_client_release): New prototype.
- (hurd_cap_client_lookup): New inline function.
- (hurd_cap_class_inhibit, hurd_cap_class_resume,
- hurd_cap_client_inhibit, hurd_cap_client_resume,
- _hurd_cap_client_end, hurd_cap_obj_inhibit, hurd_cap_obj_resume):
- New prototypes.
- * class-alloc.c (hurd_cap_class_alloc): Use CAP_CLASS->obj_slab,
- not CAP_CLASS->slab. Don't check return value of
- hurd_cap_obj_lock (as it is void now).
- * class-create.c (_hurd_cap_obj_constructor): Initialize
- OBJ->clients, OBJ->state, OBJ->pending_rpcs and OBJ->clients.
- Don't check return value of pthread_mutex_destroy.
- (_hurd_cap_obj_destructor): Destroy OBJ->clients. Don't check
- return value of pthread_mutex_destroy.
- (_hurd_cap_client_constructor, _hurd_cap_client_destructor,
- _hurd_cap_client_death, hurd_cap_class_init): New functions.
- (hurd_cap_class_create): Rewritten in terms of
- hurd_cap_class_init.
- * class-dealloc.c (hurd_cap_class_dealloc): Rename to ...
- (_hurd_cap_class_dealloc): ... this. Do not check return value of
- now void hurd_cap_obj_unlock function. Assert OBJ->state and
- OBJ->pending_rpcs. Use CAP_CLASS->obj_slab, not CAP_CLASS->slab.
- * class-destroy.c: Do not include <assert.h>.
- (_hurd_cap_client_try_destroy): New function.
- (hurd_cap_class_destroy): Rewritten.
- (hurd_cap_class_free): New function.
-
- * task-death.h (task_death_notify_t): Fix return type (should be
- void, not void *).
-
-2004-03-23 Marcus Brinkmann <marcus@gnu.org>
-
- * Makefile.am (includehurd_HEADERS): Add table.h and task-death.h.
- (libhurd_cap_server_a_SOURCES): Add task-death.c, remove table.h.
- * task-death.h, task-death.c: New files.
- * headers.m4: Add task-death.h.
-
- * table.h (_HURD_TABLE_ALIGN): New macro.
- (HURD_TABLE_INITIALIZER): Use it for ENTRY_SIZE.
-
- * Makefile.am (AM_CFLAGS): New variable.
- * headers.m4: Add table.h.
- * table.h (hurd_table_entry_t): Type removed.
- (struct hurd_table): Change type of DATA to char *. New member
- ENTRY_SIZE.
- (HURD_TABLE_INITIALIZER): Take argument SIZE_OF_ONE. Initialize
- ENTRY_SIZE.
- (hurd_table_init): Add new argument ENTRY_SIZE to prototype.
- (hurd_table_enter): Change type of DATA to void *.
- (hurd_table_lookup): Change return type to void *. Return 0, not
- HURD_TABLE_EMPTY. Reimplement for new semantics.
- * table.c: Include <assert.h>.
- (hurd_table_init): Add new argument ENTRY_SIZE. Pass it to
- HURD_TABLE_INITIALIZER.
- (hurd_table_enter): Use TABLE->entry_size for reallocation.
- Adjust code to fit new semantics. Add 1 to TABLE->first_free to
- make that point to the element after the one we just added.
-
- * Makefile.am (libhurd_cap_server_a_SOURCES): Add table.h, table.c.
- * table.h, table.c: New files.
-
-2004-03-21 Marcus Brinkmann <marcus@gnu.org>
-
- * cap-server.h (hurd_cap_obj_rele): Require at least two
- references.
-
- * Initial release.
diff --git a/libhurd-cap-server/Makefile.am b/libhurd-cap-server/Makefile.am
deleted file mode 100644
index 1d0c400..0000000
--- a/libhurd-cap-server/Makefile.am
+++ /dev/null
@@ -1,41 +0,0 @@
-# Makefile.am - Makefile template for libhurd-cap-server.
-# Copyright (C) 2004, 2005 Free Software Foundation, Inc.
-# Written by Marcus Brinkmann.
-#
-# 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.
-
-lib_LIBRARIES = libhurd-cap-server.a
-
-includehurddir = $(includedir)/hurd
-includehurd_HEADERS = cap-server.h
-
-# FIXME: Build a special libhurd-ihash.a using libc-parts for the rootservers,
-# and a normal for everybody else.
-AM_CPPFLAGS = -I$(top_builddir)/include -I$(top_srcdir)/libc-parts
-AM_CFLAGS = -std=gnu99
-libhurd_cap_server_a_SOURCES = table.h table.c \
- task-death.h task-death.c \
- cap-server-intern.h class-init.c class-create.c \
- class-destroy.c class-free.c \
- class-alloc.c class-inhibit.c \
- obj-dealloc.c obj-drop.c obj-inhibit.c \
- obj-entry-space.c obj-copy-out.c \
- client-create.c client-release.c client-inhibit.c \
- bucket-create.c bucket-free.c bucket-inhibit.c \
- bucket-manage-mt.c bucket-worker-alloc.c bucket-inject.c \
- ctx-cap-use.c
diff --git a/libhurd-cap-server/README b/libhurd-cap-server/README
deleted file mode 100644
index ce19f55..0000000
--- a/libhurd-cap-server/README
+++ /dev/null
@@ -1,185 +0,0 @@
-TODO:
-
-* Keep track of number of allocated capabilities or otherwise enable
- to check if a bucket is still in use!!! (so at least a per-client
- count is required).
-* Implement bucket-inhibit correctly. !!! Also see:
-* Decide if it is needed to allow capability allocation
- outside of RPCs (as return arguments). In that case, allocation
- must be blocked while it is checked if no extinct users exists -
- otherwise inhibiting RPCs is good enough.
-* Verify all the bucket/client stuff after rewrite.
-
-* Do we need to support soft references?
-* Extend table and hash interface to reclaim resources without
- reinitialization. !!
-* table.h/table.c should take alignment.
-
-An introduction to the capability system, server side.
-------------------------------------------------------
-
-A server provides services to its clients. In a capability system the
-right to access a given service is called a capability. This right is
-held by a client. It was previously granted to the client by the
-server. The client can then make use of this right, cease it, or
-transfer (copy) it to a new client.
-
-The capability system is object oriented. This means that the
-services granted by the server are represented by remote procedure
-calls (RPCs) invoked on server-side objects. A capability thus
-represents the right to invoke an (arbitrary) RPC on any given object.
-
-The Hurd capability system provides a flexible, yet efficient way, for
-servers to implement services for different types of objects to many
-users.
-
-The server-side objects (capability objects) are organized in
-capability classes. All capability objects in one class have the same
-basic type. Of course, the implementation of the server is free to
-make further distinctions among the objects in one class. But the
-implementation of the capability library makes certain assumptions
-about classes, and some operations always affect all objects in one
-class. Furthermore, all objects in one class share certain
-ressources. Thus, a capability class is an important organizational
-structure.
-
-For example, all open files in a file server can be implemented as one
-capability class. Another capability class could be used for all
-filesystem control capabilities.
-
-
-Capability Objects
-------------------
-
-Any server-side object you want to receive RPCs on is represented by a
-capability object. Clients are then granted access to capability
-objects, which means that they are allowed to invoke RPCs on such
-objects (see "Capabilities").
-
-All capability objects have the same basic storage size, use the same
-constructors and destructors, and are cached in the same slab
-allocator. Capability objects have their own lock and reference
-counter. The lock and reference counter are embedded at the start of
-your own definition of what a capability object should contain:
-
- struct my_cap
- {
- struct hurd_cap_obj obj;
-
- int my_own_data;
- ...
- };
-
-
-Capability objects are cached objects. They are cached in the slab
-allocator provided by libhurd-slab. This improves processor cache
-usage and allows pre-allocation, and makes it possible to keep some
-state even across object life time. The life-time of a capability
-object, and the meaning of the various constructors and destructors,
-can be seen in the following diagram:
-
- 1. Object is constructed in the cache OBJ_INIT
- 2.1. Object is instantiated and removed from the free list OBJ_ALLOC
- 2.2. Object is deallocated and put back on the free list OBJ_REINIT
- 3. Object is destroyed and removed from the cache OBJ_DESTROY
-
- Note that step 2 can occur several times, or not at all.
- This is the state diagram for each object:
-
- START ==(1.)== OBJ_INIT --(3.)--> OBJ_DESTROY = END
- | ^
- | |
- (2.1.) (3.)
- | |
- v |
- OBJ_ALLOC -(2.2.)--> OBJ_REINIT
- ^ |
- | |
- +-------(2.1.)-------+
-
-Capability objects are constructed and initialized in bursts whenever
-a new slab page is allocated for the cache. For this purpose, the
-OBJ_INIT callback is invoked. If the object is used, further
-per-instantiation initialization can be performed by OBJ_ALLOC. Each
-time this happens, the OBJ_REINIT callback is invoked when the object
-becomes deallocated and is returned to the cache. At the end of each
-objects lifetime, when the cache page is destroyed, for example due to
-memory pressure, or because the capability class is destroyed, the
-destructor callback OBJ_DESTROY is called.
-
-OBJ_ALLOC is provided because some resources may not be suitable for
-caching. In particular, OBJ_REINIT must not fail, so any resources
-that can not be safely (ie without errors) reverted to their
-initialized state are not suitable for caching and must be allocated
-with OBJ_ALLOC and destroyed with OBJ_REINIT.
-
-After having defined your own capability objects, you can create a
-capability class from these objects. A capability class is a complex
-structure that allows to grant access to capability objects to users,
-and process the incoming RPCs.
-
-
-Capability Classes
-------------------
-
-Capability classes require a capability object definition (via storage
-size and constructor/destructor callbacks), and a demuxer for
-incoming RPC messages on capability objects from this class.
-
-After creating a class, you will usually want to start a manager
-thread and call one of the RPC manage functions (multi-threaded or
-single-threaded). The manage function starts processing incoming RPCs
-immediately. You can provide a timeout or let it run indefinitely.
-If you specify a timeout, the manage function will exit if there are
-no active client connections for a certain time.
-
-You can also inhibit all RPCs on a class, from the outside or from an
-RPC handler. This will cancel all pending operations (except the
-calling one), and prevents any more messages from being processed.
-Incoming RPCs are blocked (FIXME: except interrupt_rpc).
-
-To prevent DoS attacks, only one RPC per client thread at any time is
-allowed.
-
-
-Clients
--------
-
-Each client gets a capability ID name space. In this name space,
-references for capability objects are kept. If a capability object
-gets revoked, the references become stale.
-
-
-Server Loop
------------
-
-FIXME: Should inhibit class block the server manager thread, or only
-worker threads? The former is resource lighter, the other allows to
-process interrupt messages to interrupt the operation blocking the
-class.
-
-Worker Thread Operation
------------------------
-
-0. Lock cap_class for most of the following. If necessary, first
- block until class state is green.
-1. Check cap_class->client_threads if that client is already in an RPC.
- If yes, drop the message.
-2. Is this a proper RPC? If not, it might be an initial handshake request.
- If it is an initial handshake request, lookup the task ID in
- cap_class->clients_reverse, and if it doesn't exist, add it and return.
- Otherwise proceed.
-3. Lookup the provided client id in the table cap_class->clients
- (range checked), adding a reference. If not found, drop the message.
-4. Add yourself to cap_class->pending_rpcs.
-5. Unlock the cap_class, and lock the client. If necessary, first
- block until client state is green.
-6. Lookup the capability id, adding an internal reference. If not
- found, drop the message.
-7. FIXME: Handle external references and reference container
- transactions here. Otherwise, proceed:
-8. Add ourselves to client->pending_rpcs. Unlock the client, lock the
- capability object. If necessary, first block until cap obj state is green,
-9. Add yourself to cap_obj->pending_rpcs.
-10. Process RPC.
-11. FIXME: Reverse the whole funky business.
diff --git a/libhurd-cap-server/bucket-create.c b/libhurd-cap-server/bucket-create.c
deleted file mode 100644
index e79091c..0000000
--- a/libhurd-cap-server/bucket-create.c
+++ /dev/null
@@ -1,176 +0,0 @@
-/* bucket-create.c - Create a capability bucket.
- 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. */
-
-#if HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <errno.h>
-#include <stdlib.h>
-#include <assert.h>
-#include <pthread.h>
-
-#include "cap-server-intern.h"
-
-
-/* Process the task death event for TASK_ID. */
-static void
-_hurd_cap_client_death (void *hook, hurd_task_id_t task_id)
-{
- hurd_cap_bucket_t bucket = (hurd_cap_bucket_t) hook;
- _hurd_cap_client_t client;
-
- pthread_mutex_lock (&bucket->lock);
- client = (_hurd_cap_client_t) hurd_ihash_find (&bucket->clients_reverse,
- task_id);
- if (client)
- {
- /* Found it. We will consume the "client is still living"
- reference, which can only be removed by us. As client death
- notifications are fully serialized, we don't need to take an
- extra reference now. However, we must mark the client entry
- as dead, so that no further references are acquired by
- anybody else. */
- client->dead = 1;
- }
- pthread_mutex_unlock (&bucket->lock);
-
- if (client)
- {
- error_t err;
-
- /* Inhibit all RPCs on this client. This can only fail if we
- are canceled. However, we are the task death manager thread,
- and nobody should cancel us. (FIXME: If it turns out that we
- can be canceled, we should just return on error). */
- err = _hurd_cap_client_inhibit (bucket, client);
- assert (!err);
-
- /* End RPCs on this client. There shouldn't be any (the client
- is dead), but due to small races, there is a slight chance we
- still have a worker thread blocked on an incoming message
- from the now dead client task. */
- _hurd_cap_client_end (bucket, client);
-
-#ifndef NDEBUG
- pthread_mutex_lock (&bucket->lock);
- /* Now, we should have the last reference for this client. */
- assert (client->refs == 1);
- pthread_mutex_unlock (&bucket->lock);
-#endif
-
- /* Release our, the last, reference and deallocate all
- resources, most importantly this will remove us from the
- client table of the class and release the task info
- capability. */
- _hurd_cap_client_release (bucket, client->id);
- }
-}
-
-
-/* Create a new bucket and return it in R_BUCKET. */
-error_t
-hurd_cap_bucket_create (hurd_cap_bucket_t *r_bucket)
-{
- error_t err;
- hurd_cap_bucket_t bucket;
-
- bucket = malloc (sizeof (struct _hurd_cap_bucket));
- if (!bucket)
- return errno;
-
-
- /* Client management. */
-
- err = pthread_cond_init (&bucket->client_cond, NULL);
- if (err)
- goto err_client_cond;
-
- err = pthread_mutex_init (&bucket->client_cond_lock, NULL);
- if (err)
- goto err_client_cond_lock;
-
- /* The client death notifications will be requested when we start to
- serve RPCs on the bucket. */
-
- /* Bucket management. */
-
- err = pthread_mutex_init (&bucket->lock, NULL);
- if (err)
- goto err_lock;
-
- bucket->is_managed = false;
- bucket->state = _HURD_CAP_STATE_GREEN;
-
- err = pthread_cond_init (&bucket->cond, NULL);
- if (err)
- goto err_cond;
-
- /* The member cond_waiter will be initialized when the state changes
- to _HURD_CAP_STATE_YELLOW. */
-
- bucket->nr_caps = 0;
- bucket->pending_rpcs = NULL;
- bucket->waiting_rpcs = NULL;
-
- hurd_ihash_init (&bucket->senders,
- offsetof (struct _hurd_cap_list_item, locp));
-
- err = hurd_table_init (&bucket->clients,
- sizeof (_hurd_cap_client_t));
- if (err)
- goto err_clients;
-
- hurd_ihash_init (&bucket->clients_reverse,
- offsetof (struct _hurd_cap_client, locp));
-
- /* Do not use asynchronous thread allocation by default. */
- bucket->is_worker_alloc_async = false;
- /* We have to leave bucket->worker_alloc uninitialized. That field
- and bucket->worker_alloc_state will be initialized if
- asynchronous worker thread allocation is used. */
-
- /* Finally, add the notify handler. */
- bucket->client_death_notify.notify_handler = _hurd_cap_client_death;
- bucket->client_death_notify.hook = bucket;
- hurd_task_death_notify_add (&bucket->client_death_notify);
-
- *r_bucket = bucket;
- return 0;
-
-#if 0
- /* Provided here in case more error cases are added. */
- hurd_table_destroy (&bucket->clients);
-#endif
-
- err_clients:
- pthread_cond_destroy (&bucket->cond);
- err_cond:
- pthread_mutex_destroy (&bucket->lock);
- err_lock:
- pthread_mutex_destroy (&bucket->client_cond_lock);
- err_client_cond_lock:
- pthread_cond_destroy (&bucket->client_cond);
- err_client_cond:
- free (bucket);
-
- return err;
-}
diff --git a/libhurd-cap-server/bucket-free.c b/libhurd-cap-server/bucket-free.c
deleted file mode 100644
index 5793114..0000000
--- a/libhurd-cap-server/bucket-free.c
+++ /dev/null
@@ -1,47 +0,0 @@
-/* bucket-create.c - Create a capability bucket.
- 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. */
-
-#if HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <errno.h>
-#include <stdlib.h>
-#include <assert.h>
-#include <pthread.h>
-
-#include "cap-server-intern.h"
-
-
-/* Free the bucket BUCKET, which must not be used. */
-void
-hurd_cap_bucket_free (hurd_cap_bucket_t bucket)
-{
- /* FIXME: Add some assertions to ensure it is not used.
- Reintroduce _hurd_cap_client_try_destroy. */
- hurd_table_destroy (&bucket->clients);
- pthread_cond_destroy (&bucket->cond);
- pthread_mutex_destroy (&bucket->lock);
- pthread_mutex_destroy (&bucket->client_cond_lock);
- pthread_cond_destroy (&bucket->client_cond);
- free (bucket);
-}
-
diff --git a/libhurd-cap-server/bucket-inhibit.c b/libhurd-cap-server/bucket-inhibit.c
deleted file mode 100644
index b3484bf..0000000
--- a/libhurd-cap-server/bucket-inhibit.c
+++ /dev/null
@@ -1,142 +0,0 @@
-/* bucket-inhibit.c - Inhibit RPCs on a capability bucket.
- 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. */
-
-#if HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <errno.h>
-#include <pthread.h>
-#include <stdlib.h>
-
-#include "cap-server-intern.h"
-
-
-/* Inhibit all RPCs on the capability bucket BUCKET (which must not
- be locked). You _must_ follow up with a hurd_cap_bucket_resume
- operation, and hold at least one reference to the object
- continuously until you did so. */
-error_t
-hurd_cap_bucket_inhibit (hurd_cap_bucket_t bucket)
-{
- error_t err;
-
- pthread_mutex_lock (&bucket->lock);
-
- /* First wait until any other inhibitor has resumed the bucket. If
- this function is called within an RPC, we are going to be
- canceled anyway. Otherwise, it ensures that bucket inhibitions
- are fully serialized (per bucket). */
- /* FIXME: Do something if the state is _HURD_CAP_STATE_BLACK? Can
- only happen if we are called from outside any RPCs. */
- while (bucket->state != _HURD_CAP_STATE_GREEN)
- {
- err = hurd_cond_wait (&bucket->cond, &bucket->lock);
- if (err)
- {
- /* We have been canceled. */
- pthread_mutex_unlock (&bucket->lock);
- return err;
- }
- }
-
- /* Now it is our turn to inhibit the bucket. */
- bucket->cond_waiter = pthread_self ();
-
- if (_hurd_cap_bucket_cond_busy (bucket))
- {
- _hurd_cap_list_item_t pending_rpc = bucket->pending_rpcs;
-
- /* There are still pending RPCs (beside us). Cancel them. */
- while (pending_rpc)
- {
- if (pending_rpc->thread != bucket->cond_waiter)
- pthread_cancel (pending_rpc->thread);
- pending_rpc = pending_rpc->next;
- }
-
- /* Indicate that we would like to know when they have gone. */
- bucket->state = _HURD_CAP_STATE_YELLOW;
-
- /* The last one will shut the door. */
- do
- {
- err = hurd_cond_wait (&bucket->cond, &bucket->lock);
- if (err)
- {
- /* We have been canceled ourselves. Give up. */
- bucket->state = _HURD_CAP_STATE_GREEN;
- pthread_mutex_unlock (&bucket->lock);
- return err;
- }
- }
- while (bucket->state != _HURD_CAP_STATE_RED);
- }
- else
- bucket->state = _HURD_CAP_STATE_RED;
-
- /* Now all pending RPCs have been canceled and are completed (except
- us), and all incoming RPCs are inhibited. */
- pthread_mutex_unlock (&bucket->lock);
-
- return 0;
-}
-
-
-/* Resume RPCs on the bucket BUCKET and wake-up all waiters. */
-void
-hurd_cap_bucket_resume (hurd_cap_bucket_t bucket)
-{
- pthread_mutex_lock (&bucket->lock);
-
- bucket->state = _HURD_CAP_STATE_GREEN;
-
- /* Broadcast the change to all potential waiters. */
- pthread_cond_broadcast (&bucket->cond);
-
- pthread_mutex_unlock (&bucket->lock);
-}
-
-
-/* End management of the bucket BUCKET. */
-error_t
-hurd_cap_bucket_end (hurd_cap_bucket_t bucket, bool force)
-{
- pthread_mutex_lock (&bucket->lock);
-
- if (!force && bucket->nr_caps)
- {
- pthread_mutex_unlock (&bucket->lock);
- return EBUSY;
- }
-
- bucket->state = _HURD_CAP_STATE_BLACK;
-
- /* Broadcast the change to all potential waiters. */
- pthread_cond_broadcast (&bucket->cond);
-
- if (bucket->is_managed && bucket->cond_waiter != bucket->manager)
- pthread_cancel (bucket->manager);
-
- pthread_mutex_unlock (&bucket->lock);
-
- return 0;
-}
diff --git a/libhurd-cap-server/bucket-inject.c b/libhurd-cap-server/bucket-inject.c
deleted file mode 100644
index 0a81b27..0000000
--- a/libhurd-cap-server/bucket-inject.c
+++ /dev/null
@@ -1,58 +0,0 @@
-/* bucket-inject.c - Copy out a capability to a client.
- 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. */
-
-#if HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <errno.h>
-#include <pthread.h>
-#include <stdlib.h>
-
-#include "cap-server-intern.h"
-
-
-/* Copy out a capability for the capability OBJ to the client with the
- task ID TASK_ID. Returns the capability (valid only for this user)
- in *R_CAP, or an error. It is not safe to call this from outside
- an RPC on OBJ while the manager is running. */
-error_t
-hurd_cap_bucket_inject (hurd_cap_bucket_t bucket, hurd_cap_obj_t obj,
- hurd_task_id_t task_id, hurd_cap_handle_t *r_cap)
-{
- error_t err;
- _hurd_cap_client_t client;
- _hurd_cap_id_t cap_id;
-
- err = _hurd_cap_client_create (bucket, task_id, &client);
- if (err)
- return err;
-
- pthread_mutex_lock (&obj->lock);
- err = _hurd_cap_obj_copy_out (obj, bucket, client, &cap_id);
- pthread_mutex_unlock (&obj->lock);
- _hurd_cap_client_release (bucket, client->id);
- if (err)
- return err;
-
- *r_cap = _hurd_cap_handle_make (client->id, cap_id);
- return 0;
-}
diff --git a/libhurd-cap-server/bucket-manage-mt.c b/libhurd-cap-server/bucket-manage-mt.c
deleted file mode 100644
index 15de1f1..0000000
--- a/libhurd-cap-server/bucket-manage-mt.c
+++ /dev/null
@@ -1,1116 +0,0 @@
-/* bucket-manage-mt.c - Manage RPCs on a bucket.
- Copyright (C) 2004, 2005 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. */
-
-#if HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <errno.h>
-#include <stdlib.h>
-#include <assert.h>
-#include <stdint.h>
-#include <pthread.h>
-
-#include <l4.h>
-#include <compiler.h>
-
-#include "cap-server-intern.h"
-
-
-/* When using propagation, the from thread ID returned can differ from
- the one we used for the closed receive. */
-#define l4_xreceive_timeout(from,timeout,fromp) \
- (l4_ipc (l4_nilthread, from, timeout, fromp))
-#define l4_xreceive(from,fromp) \
- l4_xreceive_timeout (from, l4_timeouts (L4_ZERO_TIME, L4_NEVER), fromp)
-
-
-/* FIXME: Throughout this file, for debugging, the behaviour could be
- relaxed to return errors to callers which would otherwise be
- ignored (due to malformed requests etc). */
-
-
-/* FIXME: This section contains a lot of random junk that maybe should
- be somewhere else (or not). */
-
-/* Cancel the pending RPC of the specified thread. */
-#define HURD_CAP_MSG_LABEL_CANCEL 0x100
-#define HURD_CAP_MSG_LABEL_GET_ROOT 0x101
-
-/* Some error for this. */
-#define ECAP_NOREPLY 0x10001
-#define ECAP_DIED 0x10002
-
-
-/* The msg labels of the reply from the worker to the manager. */
-#define _HURD_CAP_MSG_WORKER_ACCEPTED 0
-#define _HURD_CAP_MSG_WORKER_REJECTED 1
-
-struct worker_info
-{
- /* The bucket. */
- hurd_cap_bucket_t bucket;
-
- /* The manager thread. */
- l4_thread_id_t manager_tid;
-
- /* The timeout for the worker thread as an L4 time period. */
- l4_time_t timeout;
-};
-
-
-static void
-__attribute__((always_inline))
-reply_err (l4_thread_id_t to, error_t err)
-{
-#define HURD_L4_ERROR_LABEL ((uint16_t) INT16_MIN)
-#define HURD_L4_ERROR_TAG ((HURD_L4_ERROR_LABEL << 16) & 1)
- l4_msg_tag_t tag = HURD_L4_ERROR_TAG;
-
- l4_set_msg_tag (tag);
- l4_load_mr (1, err);
- l4_reply (to);
-}
-
-
-/* Lookup the client with client ID CLIENT_ID and return it in
- *R_CLIENT with one reference for the entry in the bucket. It is
- verified that the client is in fact the one with the task ID
- TASK_ID. */
-static error_t
-__attribute__((always_inline))
-lookup_client (hurd_cap_bucket_t bucket, _hurd_cap_client_id_t client_id,
- hurd_task_id_t task_id, _hurd_cap_client_t *r_client)
-{
- error_t err = 0;
- _hurd_cap_client_t *clientp;
-
- pthread_mutex_lock (&bucket->lock);
- /* Look up the client by its ID. */
- clientp = hurd_table_lookup (&bucket->clients, client_id);
- if (!clientp || (*clientp)->dead || (*clientp)->task_id != task_id)
- err = ECAP_NOREPLY;
- else
- {
- (*clientp)->refs++;
- *r_client = *clientp;
- }
- pthread_mutex_unlock (&bucket->lock);
-
- return err;
-}
-
-
-/* Process the message CTX->MSG from thread CTX->FROM in worker thread
- CTX->WORKER of bucket CTX->BUCKET. Return ECAP_NOREPLY if no reply
- should be sent. Any other error will be replied to the user. If 0
- is returned, CTX->MSG must contain the reply message. */
-static error_t
-__attribute__((always_inline))
-manage_demuxer (hurd_cap_rpc_context_t ctx, _hurd_cap_list_item_t worker)
-{
- error_t err = 0;
- hurd_cap_bucket_t bucket = ctx->bucket;
- _hurd_cap_client_t client;
- hurd_cap_class_t cap_class;
- hurd_cap_obj_t obj;
- _hurd_cap_obj_entry_t obj_entry;
- struct _hurd_cap_list_item worker_client;
- struct _hurd_cap_list_item worker_class;
- struct _hurd_cap_list_item worker_obj;
-
- worker_client.thread = worker->thread;
- worker_client.tid = worker->tid;
- worker_client.next = NULL;
- worker_client.prevp = NULL;
-
- worker_class = worker_client;
- worker_obj = worker_client;
-
- if (l4_msg_label (ctx->msg) == HURD_CAP_MSG_LABEL_GET_ROOT)
- {
- /* This is the "get the root capability" RPC. FIXME: Needs to
- be implemented. */
- return ENOSYS;
- }
-
- /* Every normal RPC must have at least one untyped word, which
- contains the client and capability ID. Otherwise the message is
- malformed, and thus ignored. */
- if (l4_untyped_words (l4_msg_msg_tag (ctx->msg)) < 1)
- return ECAP_NOREPLY;
- ctx->handle = l4_msg_word (ctx->msg, 0);
-
- err = lookup_client (bucket, _hurd_cap_client_id (ctx->handle),
- ctx->sender, &client);
- if (err)
- return err;
-
- /* At this point, CLIENT_ID and CLIENT are valid, and we have one
- reference for the client. */
-
- pthread_mutex_lock (&client->lock);
- /* First, we have to check if the class is inhibited, and if it is,
- we have to wait until it is uninhibited. */
- if (EXPECT_FALSE (client->state == _HURD_CAP_STATE_BLACK))
- err = ECAP_NOREPLY;
- else if (EXPECT_FALSE (client->state != _HURD_CAP_STATE_GREEN))
- {
- pthread_mutex_unlock (&client->lock);
- pthread_mutex_lock (&bucket->client_cond_lock);
- pthread_mutex_lock (&client->lock);
- while (!err && client->state != _HURD_CAP_STATE_GREEN)
- {
- if (client->state == _HURD_CAP_STATE_BLACK)
- err = ECAP_NOREPLY;
- else
- {
- pthread_mutex_unlock (&client->lock);
- err = hurd_cond_wait (&bucket->client_cond,
- &bucket->client_cond_lock);
- pthread_mutex_lock (&client->lock);
- }
- }
- pthread_mutex_unlock (&bucket->client_cond_lock);
- }
- if (err)
- {
- pthread_mutex_unlock (&client->lock);
- /* Either the client died, or we have been canceled. */
- _hurd_cap_client_release (bucket, client->id);
- return err;
- }
-
- {
- _hurd_cap_obj_entry_t *entry;
-
- entry = (_hurd_cap_obj_entry_t *)
- hurd_table_lookup (&client->caps, _hurd_cap_id (ctx->handle));
- if (!entry)
- err = ECAP_NOREPLY;
- else
- {
- obj_entry = *entry;
-
- if (EXPECT_FALSE (!obj_entry->external_refs))
- err = ECAP_NOREPLY;
- else if (EXPECT_FALSE (obj_entry->dead))
- err = ECAP_DIED;
- else
- {
- obj_entry->internal_refs++;
- obj = obj_entry->cap_obj;
- }
- }
- }
- if (err)
- {
- /* Either the capability ID is invalid, or it was revoked. */
- pthread_mutex_unlock (&client->lock);
- _hurd_cap_client_release (bucket, client->id);
- return err;
- }
-
- /* At this point, CAP_ID, OBJ_ENTRY and OBJ are valid. We have one
- internal reference for the capability entry. */
-
- /* Add ourself to the pending_rpcs list of the client. */
- _hurd_cap_list_item_add (&client->pending_rpcs, &worker_client);
- pthread_mutex_unlock (&client->lock);
-
- cap_class = obj->cap_class;
-
- pthread_mutex_lock (&cap_class->lock);
- /* First, we have to check if the class is inhibited, and if it is,
- we have to wait until it is uninhibited. */
- while (!err && cap_class->state != _HURD_CAP_STATE_GREEN)
- err = hurd_cond_wait (&cap_class->cond, &cap_class->lock);
- if (err)
- {
- /* Canceled. */
- pthread_mutex_unlock (&cap_class->lock);
- goto client_cleanup;
- }
-
- _hurd_cap_list_item_add (&cap_class->pending_rpcs, &worker_class);
- pthread_mutex_unlock (&cap_class->lock);
-
-
- pthread_mutex_lock (&obj->lock);
- /* First, we have to check if the object is inhibited, and if it is,
- we have to wait until it is uninhibited. */
- if (obj->state != _HURD_CAP_STATE_GREEN)
- {
- pthread_mutex_unlock (&obj->lock);
- pthread_mutex_lock (&cap_class->obj_cond_lock);
- pthread_mutex_lock (&obj->lock);
- while (!err && obj->state != _HURD_CAP_STATE_GREEN)
- {
- pthread_mutex_unlock (&obj->lock);
- err = hurd_cond_wait (&cap_class->obj_cond,
- &cap_class->obj_cond_lock);
- pthread_mutex_lock (&obj->lock);
- }
- pthread_mutex_unlock (&cap_class->obj_cond_lock);
- }
- if (err)
- {
- /* Canceled. */
- pthread_mutex_unlock (&obj->lock);
- goto class_cleanup;
- }
-
- /* Now check if the client still has the capability, or if it was
- revoked. */
- pthread_mutex_lock (&client->lock);
- if (obj_entry->dead)
- err = ECAP_DIED;
- pthread_mutex_unlock (&client->lock);
- if (err)
- {
- /* The capability was revoked in the meantime. */
- pthread_mutex_unlock (&obj->lock);
- goto class_cleanup;
- }
- _hurd_cap_list_item_add (&obj->pending_rpcs, &worker_obj);
-
- /* At this point, we have looked up the capability, acquired an
- internal reference for its entry in the client table (which
- implicitely keeps a reference acquired for the object itself),
- acquired a reference for the capability client in the bucket, and
- have added an item to the pending_rpcs lists in the client, class
- and object. The object is locked. With all this, we can finally
- start to process the message for real. */
-
- /* FIXME: Call the internal demuxer here, for things like reference
- counter modification, cap passing etc. */
-
- /* Invoke the class-specific demuxer. */
- ctx->client = client;
- ctx->obj = obj;
- err = (*cap_class->demuxer) (ctx);
-
- /* Clean up. OBJ is still locked. */
- _hurd_cap_list_item_remove (&worker_obj);
- _hurd_cap_obj_cond_check (obj);
-
- /* Instead releasing the lock for the object, we hold it until
- manage_demuxer_cleanup is called. This is important, because the
- object must be locked until the reply message is sent. Consider
- the impact of map items or string items. FIXME: Alternatively,
- let the user set a flag if the object is locked upon return (and
- must be kept lock continuously until the reply is sent). OTOH,
- releasing a lock just to take it again is also pretty useless.
- Needs performance measurements to make a good decision. */
- hurd_cap_obj_ref (obj);
-
- class_cleanup:
- pthread_mutex_lock (&cap_class->lock);
- _hurd_cap_list_item_remove (&worker_class);
- _hurd_cap_class_cond_check (cap_class);
- pthread_mutex_unlock (&cap_class->lock);
-
- client_cleanup:
- pthread_mutex_lock (&client->lock);
- _hurd_cap_list_item_remove (&worker_client);
- _hurd_cap_client_cond_check (bucket, client);
-
- /* You are not allowed to revoke a capability while there are
- pending RPCs on it. This is the reason why we know that there
- must be at least one extra internal reference. FIXME: For
- cleanliness, this could still call some inline function that does
- the decrement. The assert can be a hint to the compiler to
- optimize the inline function expansion anyway. */
- assert (!obj_entry->dead);
- assert (obj_entry->internal_refs > 1);
- obj_entry->internal_refs--;
- pthread_mutex_unlock (&client->lock);
-
- _hurd_cap_client_release (bucket, client->id);
-
- return err;
-}
-
-
-static void
-__attribute__((always_inline))
-manage_demuxer_cleanup (hurd_cap_rpc_context_t ctx)
-{
- hurd_cap_obj_drop (ctx->obj);
-}
-
-
-/* A worker thread for RPC processing. The behaviour of this function
- is tightly integrated with the behaviour of the manager thread. */
-static void *
-manage_mt_worker (void *arg, bool async)
-{
- struct worker_info *info = (struct worker_info *) arg;
- hurd_cap_bucket_t bucket = info->bucket;
- struct _hurd_cap_list_item worker_item;
- _hurd_cap_list_item_t worker = &worker_item;
- l4_thread_id_t manager = info->manager_tid;
- l4_time_t timeout = info->timeout;
- l4_thread_id_t from;
- l4_msg_tag_t msg_tag;
- bool current_worker_is_us;
-
- /* Prepare the worker queue item. [SYNC: As we are always the
- current worker thread when we are started up, we do not add
- ourselves to the free list.] */
- worker->thread = pthread_self ();
- worker->tid = l4_myself ();
- worker->next = NULL;
- worker->prevp = NULL;
-
- if (EXPECT_FALSE (async))
- {
- /* We have to add ourselves to the free list and inform the
- worker_alloc_async thread. */
- pthread_mutex_lock (&bucket->lock);
-
- if (bucket->is_manager_waiting && !bucket->free_worker)
- {
- /* The manager is starving for worker threads. */
- pthread_cond_broadcast (&bucket->cond);
- }
- _hurd_cap_list_item_add (&bucket->free_worker, worker);
-
- /* Notify the worker_alloc_async thread that we have started up
- and added ourselves to the free list. */
- bucket->worker_alloc_state = _HURD_CAP_STATE_RED;
-
- /* This will wake up the worker_alloc_async thread, but also the
- manager in case it is blocked on getting a new worker
- thread. */
- pthread_cond_broadcast (&bucket->cond);
- pthread_mutex_unlock (&bucket->lock);
-
- /* We do not know if we will be the current worker thread or
- not, so we must wait with a timeout. */
- msg_tag = l4_xreceive_timeout (manager, timeout, &from);
- }
- else
- {
- /* When we are started up, we are supposed to listen as soon as
- possible to the next incoming message. When we know we are the
- current worker thread, we do this without a timeout. */
- msg_tag = l4_xreceive (manager, &from);
- }
-
- while (1)
- {
- if (EXPECT_FALSE (l4_ipc_failed (msg_tag)))
- {
- /* Slow path. */
-
- l4_word_t err_code = l4_error_code ();
- l4_word_t ipc_err = (err_code >> 1) & 0x7;
-
- if (ipc_err == L4_IPC_CANCELED || ipc_err == L4_IPC_ABORTED)
- /* We have been canceled for shutdown. */
- break;
-
- /* The only other error that can happen is a timeout waiting
- for the message. */
- assert (ipc_err == L4_IPC_TIMEOUT);
-
- pthread_mutex_lock (&bucket->lock);
- /* If we are not on the free queue, we are the current worker. */
- current_worker_is_us = _hurd_cap_list_item_dequeued (worker);
- pthread_mutex_unlock (&bucket->lock);
-
- /* If we are not the current worker, then we can just exit
- now because of our timeout. */
- if (!current_worker_is_us)
- break;
-
- /* If we are the current worker, we should wait here for the
- next message without a timeout. */
- msg_tag = l4_xreceive (manager, &from);
- /* From here, we will loop all over to the beginning of the
- while(1) block. */
- }
- else
- {
- /* Fast path. Process the RPC. */
- error_t err = 0;
- struct hurd_cap_rpc_context ctx;
- bool inhibited = false;
-
- /* IMPORTANT NOTE: The manager thread is blocked until we
- reply a message with a label MSG_ACCEPTED or
- MSG_REJECTED. We are supposed to return such a message
- as quickly as possible. In the accepted case, we should
- then process the message, while in the rejected case we
- should rapidly go into the next receive. */
-
- /* Before we can work on the message, we need to copy it.
- This is because the MRs holding the message might be
- overridden by the pthread implementation or other
- function calls we make. In particular,
- pthread_mutex_lock is can mangle the message buffer. */
- l4_msg_store (msg_tag, ctx.msg);
-
- assert (l4_ipc_propagated (msg_tag));
- assert (l4_is_thread_equal (l4_actual_sender (), manager));
-
- pthread_mutex_lock (&bucket->lock);
- /* We process cancellation messages regardless of the
- bucket state. */
- if (EXPECT_FALSE (l4_msg_label (ctx.msg)
- == HURD_CAP_MSG_LABEL_CANCEL))
- {
- if (l4_untyped_words (l4_msg_msg_tag (ctx.msg)) == 1)
- {
- l4_thread_id_t tid = l4_msg_word (ctx.msg, 0);
-
- /* First verify access. Threads are only allowed to
- cancel RPCs from other threads in the task. */
- if (hurd_task_id_from_thread_id (tid)
- == hurd_task_id_from_thread_id (from))
- {
- /* We allow cancel requests even if normal RPCs
- are inhibited. */
- _hurd_cap_list_item_t pending_worker;
-
- pending_worker = hurd_ihash_find (&bucket->senders,
- tid);
- if (!pending_worker)
- reply_err (from, ESRCH);
- else
- {
- /* Found it. Cancel it. */
- pthread_cancel (pending_worker->thread);
- /* Reply success. */
- reply_err (from, 0);
- }
- }
- }
- /* Set the error variable so that we return to the
- manager immediately. */
- err = ECAP_NOREPLY;
- }
- else
- {
- /* Normal RPCs. */
- if (EXPECT_FALSE (bucket->state == _HURD_CAP_STATE_BLACK))
- {
- /* The bucket operations have been ended, and the
- manager has already been canceled. We know that
- the BUCKET->senders hash is empty, so we can
- quickly process the message. */
-
- /* This is a normal RPC. We cancel it immediately. */
- reply_err (from, ECANCELED);
-
- /* Now set ERR to any error, so we return to the
- manager. */
- err = ECAP_NOREPLY; /* Doesn't matter which error. */
- }
- else
- {
- if (EXPECT_FALSE (bucket->state != _HURD_CAP_STATE_GREEN))
- {
- /* If we are inhibited, we will have to wait
- until we are uninhibited. */
- inhibited = true;
- }
-
- /* FIXME: This is inefficient. ihash should support
- an "add if not there" function. */
- if (EXPECT_FALSE (hurd_ihash_find (&bucket->senders, from)))
- err = EBUSY;
- else
- {
- /* FIXME: We know intimately that pthread_self is not
- _HURD_IHASH_EMPTY or _HURD_IHASH_DELETED. */
- err = hurd_ihash_add (&bucket->senders, from, worker);
- }
- }
- }
-
- if (EXPECT_FALSE (err))
- {
- pthread_mutex_unlock (&bucket->lock);
-
- /* Either we already processed the message above, or
- this user thread is currently in an RPC. We don't
- allow asynchronous operation for security reason
- (preventing DoS attacks). Silently drop the
- message. */
- msg_tag = l4_niltag;
- l4_set_msg_label (&msg_tag, _HURD_CAP_MSG_WORKER_REJECTED);
- l4_load_mr (0, msg_tag);
-
- /* Reply to the manager that we don't accept the message
- and wait for the next message without a timeout
- (because now we know we are the current worker). */
- from = manager;
- msg_tag = l4_lreply_wait (manager, &from);
-
- /* From here, we will loop all over to the beginning of
- the while(1) block. */
- }
- else
- {
- _hurd_cap_list_item_add (inhibited ? &bucket->waiting_rpcs
- : &bucket->pending_rpcs, worker);
- pthread_mutex_unlock (&bucket->lock);
-
- msg_tag = l4_niltag;
- l4_set_msg_label (&msg_tag, _HURD_CAP_MSG_WORKER_ACCEPTED);
- l4_load_mr (0, msg_tag);
- msg_tag = l4_reply (manager);
- assert (l4_ipc_succeeded (msg_tag));
-
- /* Now we are "detached" from the manager in the sense
- that we are not the current worker thread
- anymore. */
-
- if (EXPECT_FALSE (inhibited))
- {
- pthread_mutex_lock (&bucket->lock);
- while (!err && bucket->state != _HURD_CAP_STATE_GREEN
- && bucket->state != _HURD_CAP_STATE_BLACK)
- err = hurd_cond_wait (&bucket->cond, &bucket->lock);
- if (!err)
- {
- if (bucket->state == _HURD_CAP_STATE_BLACK)
- err = ECANCELED;
- else
- {
- /* State is _HURD_CAP_STATE_GREEN. Move
- ourselves to the pending RPC list. */
- _hurd_cap_list_item_remove (worker);
- _hurd_cap_list_item_add (&bucket->pending_rpcs,
- worker);
- }
- }
- pthread_mutex_unlock (&bucket->lock);
- }
-
- if (EXPECT_TRUE (!err))
- {
- /* Process the message. */
- ctx.sender = hurd_task_id_from_thread_id (from);
- ctx.bucket = bucket;
- ctx.from = from;
- ctx.obj = NULL;
- err = manage_demuxer (&ctx, worker);
- }
-
- /* Post-processing. */
-
- pthread_mutex_lock (&bucket->lock);
- /* We have to add ourselves to the free list before (or
- at the same time) as removing the client from the
- pending hash, and before replying to the RPC (if we
- reply in the worker thread at all). The former is
- necessary to make sure that no new thread is created
- in the race that would otherwise exist, namely after
- replying and before adding ourself to the free list.
- The latter is required because a client that
- immediately follows up with a new message of course
- can expect that to work properly. */
-
- if (EXPECT_FALSE (bucket->is_manager_waiting
- && !bucket->free_worker))
- {
- /* The manager is starving for worker threads. */
- pthread_cond_broadcast (&bucket->cond);
- }
-
- /* Remove from pending_rpcs (or waiting_rpcs) list. */
- _hurd_cap_list_item_remove (worker);
- /* The last waiting RPC may have to signal the manager. */
- if (EXPECT_FALSE (inhibited
- && bucket->state == _HURD_CAP_STATE_BLACK
- && !bucket->waiting_rpcs))
- pthread_cond_broadcast (&bucket->cond);
- _hurd_cap_list_item_add (&bucket->free_worker, worker);
-
- _hurd_cap_bucket_cond_check (bucket);
-
- /* Now that we are back on the free list it is safe to
- let in the next RPC by this thread. */
- hurd_ihash_locp_remove (&bucket->senders, worker->locp);
-
- /* FIXME: Reap the cancellation flag here. If it was
- set, we have been effectively unblocked now. From
- now on, canceling us means something different than
- cancelling a pending RPC (it means terminating the
- worker thread). */
-
- pthread_mutex_unlock (&bucket->lock);
-
- /* Finally, return the reply message, if appropriate. */
- if (EXPECT_TRUE (err != ECAP_NOREPLY))
- {
- if (EXPECT_FALSE (err))
- reply_err (from, err);
- else
- {
- /* We must make sure the message tag is set. */
- l4_msg_tag_t tag = l4_msg_msg_tag (ctx.msg);
- l4_clear_propagation (&tag);
- l4_set_msg_msg_tag (ctx.msg, tag);
- l4_msg_load (ctx.msg);
- l4_reply (from);
- }
- }
-
- if (ctx.obj)
- manage_demuxer_cleanup (&ctx);
-
- /* Now listen for the next message, with a timeout. */
- from = manager;
- msg_tag = l4_xreceive_timeout (manager, timeout, &from);
-
- /* From here, we will loop to the beginning of the
- while(1) block. */
- }
- }
- }
-
- /* At this point, we have been canceled while being on the free
- list, so we should go away. */
-
- pthread_mutex_lock (&bucket->lock);
- if (_hurd_cap_list_item_dequeued (worker))
- {
- /* We are the current worker thread. We are the last worker
- thread the manager thread will cancel. */
- pthread_cond_broadcast (&bucket->cond);
- }
- else
- {
- _hurd_cap_list_item_remove (worker);
- if (bucket->is_manager_waiting && !bucket->free_worker)
- {
- /* The manager is shutting down. We are the last free
- worker (except for the current worker thread) to be
- canceled. */
- pthread_cond_broadcast (&bucket->cond);
- }
- }
- pthread_mutex_unlock (&bucket->lock);
-
- return NULL;
-}
-
-
-/* A worker thread for RPC processing. The behaviour of this function
- is tightly integrated with the behaviour of the manager thread. */
-static void *
-manage_mt_worker_sync (void *arg)
-{
- return manage_mt_worker (arg, false);
-}
-
-
-/* A worker thread for RPC processing. The behaviour of this function
- is tightly integrated with the behaviour of the manager thread. */
-static void *
-manage_mt_worker_async (void *arg)
-{
- return manage_mt_worker (arg, true);
-}
-
-
-/* Return the next free worker thread. If no free worker thread is
- available, create a new one. If that fails, block until one
- becomes free. If we are interrupted while blocking, return
- l4_nilthread. */
-static l4_thread_id_t
-manage_mt_get_next_worker (struct worker_info *info, pthread_t *worker_thread)
-{
- hurd_cap_bucket_t bucket = info->bucket;
- l4_thread_id_t worker = l4_nilthread;
- _hurd_cap_list_item_t worker_item;
-
- pthread_mutex_lock (&bucket->lock);
-
- if (EXPECT_FALSE (bucket->free_worker == NULL))
- {
- /* Slow path. Create a new thread and use that. */
- error_t err;
-
- pthread_mutex_unlock (&bucket->lock);
- worker = pthread_pool_get_np ();
- if (worker == l4_nilthread)
- err = EAGAIN;
- else
- {
- err = pthread_create_from_l4_tid_np (worker_thread, NULL,
- worker, manage_mt_worker_sync,
- info);
- /* Return the thread to the pool. */
- if (err)
- pthread_pool_add_np (worker);
- }
-
- if (!err)
- {
- pthread_detach (*worker_thread);
- return worker;
- }
- else
- {
- pthread_mutex_lock (&bucket->lock);
- if (!bucket->free_worker)
- {
- /* Creating a new thread failed. As a last resort, put
- ourself to sleep until we are woken up by the next
- free worker. Hopefully not all workers are blocking
- forever. */
-
- /* FIXME: To fix the case where all workers are blocking
- forever, cancel one (or more? all?) (random? oldest?)
- worker threads. Usually, that user will restart, but
- it will nevertheless allow us to make some (although
- slow) process. */
-
- /* The next worker thread that adds itself to the free
- list will broadcast the condition. */
- bucket->is_manager_waiting = true;
- do
- err = hurd_cond_wait (&bucket->cond, &bucket->lock);
- while (!err && !bucket->free_worker);
-
- if (err)
- {
- pthread_mutex_unlock (&bucket->lock);
- return l4_nilthread;
- }
- }
- }
- }
-
- /* Fast path. A worker thread is available. Remove it from the
- free list and use it. */
- worker_item = bucket->free_worker;
- _hurd_cap_list_item_remove (worker_item);
- pthread_mutex_unlock (&bucket->lock);
-
- *worker_thread = worker_item->thread;
- return worker_item->tid;
-}
-
-
-/* A worker thread for allocating new worker threads. Only used if
- asynchronous worker thread allocation is requested. This is only
- necessary (and useful) for physmem, to break out of a potential
- dead-lock with the task server. */
-static void *
-worker_alloc_async (void *arg)
-{
- struct worker_info *info = (struct worker_info *) arg;
- hurd_cap_bucket_t bucket = info->bucket;
- error_t err;
-
- pthread_mutex_lock (&bucket->lock);
- if (bucket->state == _HURD_CAP_STATE_BLACK)
- {
- pthread_mutex_unlock (&bucket->lock);
- return NULL;
- }
-
- while (1)
- {
- err = hurd_cond_wait (&bucket->cond, &bucket->lock);
- /* We ignore the error, as the only error that can occur is
- ECANCELED, and only if the bucket state has gone to black for
- shutdown. */
- if (bucket->state == _HURD_CAP_STATE_BLACK)
- break;
-
- if (bucket->worker_alloc_state == _HURD_CAP_STATE_GREEN)
- {
- l4_thread_id_t worker = l4_nilthread;
- pthread_t worker_thread;
-
- pthread_mutex_unlock (&bucket->lock);
-
- worker = pthread_pool_get_np ();
- if (worker == l4_nilthread)
- err = EAGAIN;
- else
- {
- err = pthread_create_from_l4_tid_np (&worker_thread, NULL,
- worker,
- manage_mt_worker_async,
- info);
- /* Return the thread to the pool. */
- if (err)
- pthread_pool_add_np (worker);
- }
-
- if (!err)
- {
- pthread_detach (worker_thread);
-
- pthread_mutex_lock (&bucket->lock);
- bucket->worker_alloc_state = _HURD_CAP_STATE_YELLOW;
- /* We ignore any error, as the only error that can occur
- is ECANCELED, and only if the bucket state goes to
- black for shutdown. But particularly in that case we
- want to wait until the thread has fully come up and
- entered the free list, so it's properly accounted for
- and will be canceled at shutdown by the manager. */
- while (bucket->worker_alloc_state == _HURD_CAP_STATE_YELLOW)
- err = hurd_cond_wait (&bucket->cond, &bucket->lock);
-
- /* Will be set by the started thread. */
- assert (bucket->worker_alloc_state == _HURD_CAP_STATE_RED);
- }
- else
- {
- pthread_mutex_lock (&bucket->lock);
- bucket->worker_alloc_state = _HURD_CAP_STATE_RED;
- }
-
- if (bucket->state == _HURD_CAP_STATE_BLACK)
- break;
- }
- }
-
- bucket->worker_alloc_state = _HURD_CAP_STATE_BLACK;
- pthread_mutex_unlock (&bucket->lock);
-
- return NULL;
-}
-
-
-
-/* Start managing RPCs on the bucket BUCKET. The ROOT capability
- object, which must be unlocked and have one reference throughout
- the whole time this function runs, is used for bootstrapping client
- connections. The GLOBAL_TIMEOUT parameter specifies the number of
- seconds until the manager times out (if there are no active users).
- The WORKER_TIMEOUT parameter specifies the number of seconds until
- each worker thread times out (if there are no RPCs processed by the
- worker thread).
-
- If this returns ECANCELED, then hurd_cap_bucket_end was called with
- the force flag being true while there were still active users. If
- this returns without any error, then the timeout expired, or
- hurd_cap_bucket_end was called without active users. */
-error_t
-hurd_cap_bucket_manage_mt (hurd_cap_bucket_t bucket,
- hurd_cap_obj_t root,
- unsigned int global_timeout_sec,
- unsigned int worker_timeout_sec)
-{
- error_t err;
- l4_time_t global_timeout;
- pthread_t worker_thread;
- l4_thread_id_t worker;
- struct worker_info info;
- _hurd_cap_list_item_t item;
-
- global_timeout = (global_timeout_sec == 0) ? L4_NEVER
- : l4_time_period (UINT64_C (1000000) * global_timeout_sec);
-
- info.bucket = bucket;
- info.manager_tid = l4_myself ();
- info.timeout = (worker_timeout_sec == 0) ? L4_NEVER
- : l4_time_period (UINT64_C (1000000) * worker_timeout_sec);
-
- /* We create the first worker thread ourselves, to catch any
- possible error at this stage and bail out properly if needed. */
- worker = pthread_pool_get_np ();
- if (worker == l4_nilthread)
- return EAGAIN;
- err = pthread_create_from_l4_tid_np (&worker_thread, NULL,
- worker, manage_mt_worker_sync, &info);
- if (err)
- {
- /* Return the thread to the pool. */
- pthread_pool_add_np (worker);
- return err;
- }
- pthread_detach (worker_thread);
-
- pthread_mutex_lock (&bucket->lock);
- if (bucket->is_worker_alloc_async)
- {
- /* Prevent creation of new worker threads initially. */
- bucket->worker_alloc_state = _HURD_CAP_STATE_RED;
-
- /* Asynchronous worker thread allocation is requested. */
- err = pthread_create (&bucket->worker_alloc, NULL,
- worker_alloc_async, &info);
-
- if (err)
- {
- /* Cancel the worker thread. */
- pthread_cancel (worker_thread);
- hurd_cond_wait (&bucket->cond, &bucket->lock);
- pthread_mutex_unlock (&bucket->lock);
- return err;
- }
- }
- bucket->manager = pthread_self ();
- bucket->is_managed = true;
- bucket->is_manager_waiting = false;
- pthread_mutex_unlock (&bucket->lock);
-
- while (1)
- {
- l4_thread_id_t from = l4_anythread;
- l4_msg_tag_t msg_tag;
-
- /* We never accept any map or grant items. FIXME: For now, we
- also do not accept any string buffer items. */
- l4_accept (L4_UNTYPED_WORDS_ACCEPTOR);
-
- /* Because we do not accept any string items, we do not actually
- need to set the Xfer timeouts. But this is what we want to set
- them to when we eventually do support string items. */
- l4_set_xfer_timeouts (l4_timeouts (L4_ZERO_TIME, L4_ZERO_TIME));
-
- /* FIXME: Make sure we have enabled deferred cancellation, and
- use an L4 ipc() stub that supports that. In fact, this must
- be true for most of the IPC operations in this file. */
- msg_tag = l4_wait_timeout (global_timeout, &from);
-
- if (EXPECT_FALSE (l4_ipc_failed (msg_tag)))
- {
- l4_word_t err_code = l4_error_code ();
-
- /* FIXME: We need a macro or inline function for that. */
- l4_word_t ipc_err = (err_code >> 1) & 0x7;
-
- /* There are two possible errors, cancellation or timeout.
- Any other error indicates a bug in the code. */
- if (ipc_err == L4_IPC_CANCELED || ipc_err == L4_IPC_ABORTED)
- {
- /* If we are canceled, then this means that our state is
- now _HURD_CAP_STATE_BLACK and we should end managing
- RPCs even if there are still active users. */
-
- pthread_mutex_lock (&bucket->lock);
- assert (bucket->state == _HURD_CAP_STATE_BLACK);
- err = ECANCELED;
- break;
- }
- else
- {
- assert (((err_code >> 1) & 0x7) == L4_IPC_TIMEOUT);
-
- pthread_mutex_lock (&bucket->lock);
- /* Check if we can time out safely. */
- if (bucket->state == _HURD_CAP_STATE_GREEN
- && !bucket->nr_caps && !bucket->pending_rpcs
- && !bucket->waiting_rpcs)
- {
- err = 0;
- break;
- }
- pthread_mutex_unlock (&bucket->lock);
- }
- }
- else
- {
- /* Propagate the message to the worker thread. */
- l4_set_propagation (&msg_tag);
- l4_set_virtual_sender (from);
- l4_set_msg_tag (msg_tag);
-
- /* FIXME: Make sure to use a non-cancellable l4_lcall that
- does preserve any pending cancellation flag for this
- thread. Alternatively, we can handle cancellation here
- (reply ECANCELED to user, and enter shutdown
- sequence. */
- msg_tag = l4_lcall (worker);
- assert (l4_ipc_succeeded (msg_tag));
-
- if (EXPECT_TRUE (l4_label (msg_tag)
- == _HURD_CAP_MSG_WORKER_ACCEPTED))
- {
- worker = manage_mt_get_next_worker (&info, &worker_thread);
- if (worker == l4_nilthread)
- {
- /* The manage_mt_get_next_worker thread was
- canceled. In this case we have to terminate
- ourselves. */
- err = hurd_cap_bucket_inhibit (bucket);
- assert (!err);
- hurd_cap_bucket_end (bucket, true);
-
- pthread_mutex_lock (&bucket->lock);
- err = ECANCELED;
- break;
- }
- }
- }
- }
-
- /* At this point, bucket->lock is held. Start the shutdown
- sequence. */
- assert (!bucket->pending_rpcs);
-
- /* First shutdown the allocator thread, if any. */
- if (bucket->is_worker_alloc_async)
- {
- pthread_cancel (bucket->worker_alloc);
- pthread_join (bucket->worker_alloc, NULL);
- }
-
- /* Now force all the waiting rpcs onto the free list. They will
- have noticed the state change to _HURD_CAP_STATE_BLACK already,
- we just have to block until the last one wakes us up. */
- while (bucket->waiting_rpcs)
- hurd_cond_wait (&bucket->cond, &bucket->lock);
-
- /* Cancel the free workers. */
- item = bucket->free_worker;
- while (item)
- {
- pthread_cancel (item->thread);
- item = item->next;
- }
-
- /* Request the condition to be broadcasted. */
- bucket->is_manager_waiting = true;
-
- while (bucket->free_worker)
- {
- /* We ignore cancellations at this point, because we are already
- shutting down. */
- hurd_cond_wait (&bucket->cond, &bucket->lock);
- }
-
- /* Now cancel the current worker, except if we were canceled while
- trying to get a new one (in which case there is no current
- worker). */
- if (worker != l4_nilthread)
- {
- pthread_cancel (worker_thread);
- hurd_cond_wait (&bucket->cond, &bucket->lock);
- }
-
- bucket->is_managed = false;
- pthread_mutex_unlock (&bucket->lock);
-
- return err;
-}
diff --git a/libhurd-cap-server/bucket-worker-alloc.c b/libhurd-cap-server/bucket-worker-alloc.c
deleted file mode 100644
index be1167d..0000000
--- a/libhurd-cap-server/bucket-worker-alloc.c
+++ /dev/null
@@ -1,51 +0,0 @@
-/* bucket-worker-alloc.c - Set the worker allocation policy.
- 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. */
-
-#if HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <errno.h>
-
-#include "cap-server-intern.h"
-
-
-/* If ASYNC is true, allocate worker threads asynchronously whenever
- the number of worker threads is exhausted. This is only actually
- required for physmem (the physical memory server), to allow to
- break out of a dead-lock between physmem and the task server. It
- should be unnecessary for any other server.
-
- The default is to false, which means that worker threads are
- allocated synchronously by the manager thread.
-
- This function should be called before the manager is started with
- hurd_cap_bucket_manage_mt. It is only used for the multi-threaded
- RPC manager. */
-error_t
-hurd_cap_bucket_worker_alloc (hurd_cap_bucket_t bucket, bool async)
-{
- pthread_mutex_lock (&bucket->lock);
- bucket->is_worker_alloc_async = async;
- pthread_mutex_unlock (&bucket->lock);
-
- return 0;
-}
diff --git a/libhurd-cap-server/cap-server-intern.h b/libhurd-cap-server/cap-server-intern.h
deleted file mode 100644
index 8d87116..0000000
--- a/libhurd-cap-server/cap-server-intern.h
+++ /dev/null
@@ -1,599 +0,0 @@
-/* cap-server-intern.h - Internal interface to the Hurd capability library.
- Copyright (C) 2004, 2005 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_CAP_SERVER_INTERN_H
-#define _HURD_CAP_SERVER_INTERN_H 1
-
-#include <hurd/types.h>
-#include <hurd/ihash.h>
-#include <hurd/cap-server.h>
-
-#include <compiler.h>
-
-#include "table.h"
-#include "task-death.h"
-
-
-/* FIXME: For now. */
-#define hurd_cond_wait pthread_cond_wait
-
-/* Every capability hurd_cap_handle_t consists of two parts: The upper
- part is a client ID and the lower part is a capability object ID.
- The client ID is as long as the task ID (which is as long as the
- version ID). The cap ID occupies the remainder. We intimately
- know that even on 64 bit architectures, both fit into a 32 bit
- integer value. */
-#define _HURD_CAP_CLIENT_ID_BITS HURD_TASK_ID_BITS
-#define _HURD_CAP_ID_BITS ((sizeof (hurd_cap_handle_t) * 8) \
- - HURD_TASK_ID_BITS)
-
-#define _HURD_CAP_CLIENT_ID_MASK \
- ((L4_WORD_C(1) << _HURD_CAP_CLIENT_ID_BITS) - 1)
-#define _HURD_CAP_ID_MASK ((L4_WORD_C(1) << _HURD_CAP_ID_BITS) - 1)
-
-typedef l4_uint32_t _hurd_cap_id_t;
-typedef l4_uint32_t _hurd_cap_client_id_t;
-
-
-/* Get the capability ID from a user capability. The capabililty ID
- is an index into the caps table of a client. */
-static inline _hurd_cap_client_id_t
-__attribute__((always_inline))
-_hurd_cap_client_id (hurd_cap_handle_t cap)
-{
- return cap >> _HURD_CAP_ID_BITS;
-}
-
-
-/* Get the capability ID from a user capability. The capabililty ID
- is an index into the caps table of a client. */
-static inline _hurd_cap_id_t
-__attribute__((always_inline))
-_hurd_cap_id (hurd_cap_handle_t cap)
-{
- return cap & _HURD_CAP_ID_MASK;
-}
-
-
-/* Create a new capability handle from the client and cap ID. */
-static inline hurd_cap_handle_t
-__attribute__((always_inline))
-_hurd_cap_handle_make (_hurd_cap_client_id_t client_id, _hurd_cap_id_t cap_id)
-{
- return ((client_id & _HURD_CAP_CLIENT_ID_MASK) << _HURD_CAP_ID_BITS)
- | (cap_id & _HURD_CAP_ID_MASK);
-}
-
-
-/* This is a simple list item, used to maintain lists of pending RPC
- worker threads in a class, client or capability object. */
-struct _hurd_cap_list_item
-{
- _hurd_cap_list_item_t next;
- _hurd_cap_list_item_t *prevp;
-
- union
- {
- /* Used for maintaining lists of pending RPC worker threads in a
- class, client or capability object. */
- struct
- {
- /* This location pointer is used for fast removal from the
- BUCKET->senders. */
- hurd_ihash_locp_t locp;
-
- /* The worker thread processing the RPC. */
- pthread_t thread;
-
- /* The worker thread L4 thread ID. */
- l4_thread_id_t tid;
- };
-
- /* Used for reverse lookup of capability clients using a
- capability object. */
- struct
- {
- _hurd_cap_client_t client;
- };
- };
-};
-
-/* Add the list item ITEM to the list LIST. */
-static inline void
-__attribute__((always_inline))
-_hurd_cap_list_item_add (_hurd_cap_list_item_t *list,
- _hurd_cap_list_item_t item)
-{
- if (*list)
- (*list)->prevp = &item->next;
- item->prevp = list;
- item->next = *list;
- *list = item;
-}
-
-
-/* Remove the list item ITEM from the list. */
-static inline void
-__attribute__((always_inline))
-_hurd_cap_list_item_remove (_hurd_cap_list_item_t item)
-{
- if (item->next)
- item->next->prevp = item->prevp;
- *(item->prevp) = item->next;
- item->prevp = NULL;
-}
-
-
-/* Check if the item ITEM is dequeued or not. */
-static inline bool
-__attribute__((always_inline))
-_hurd_cap_list_item_dequeued (_hurd_cap_list_item_t item)
-{
- return item->prevp == NULL;
-}
-
-
-/* Deallocate the capability object OBJ, which must be locked and have
- no more references. */
-void _hurd_cap_obj_dealloc (hurd_cap_obj_t obj)
- __attribute__((visibility("hidden")));
-
-
-/* Remove one reference for the capability object OBJ, which must be
- locked, and will be unlocked when the function returns. If this
- was the last user of this object, the object is deallocated. */
-static inline void
-_hurd_cap_obj_drop (hurd_cap_obj_t obj)
-{
- if (EXPECT_TRUE (!atomic_decrement_and_test (&obj->refs)))
- hurd_cap_obj_unlock (obj);
- else
- _hurd_cap_obj_dealloc (obj);
-}
-
-
-/* Client capabilities. */
-
-/* The following data type is used pointed to by an entry in the caps
- table of a client. Except noted otherwise, its members are
- protected by the same lock as the table. */
-struct _hurd_cap_obj_entry
-{
- /* The capability object. */
- hurd_cap_obj_t cap_obj;
-
- /* The index in the capability table. */
- _hurd_cap_id_t id;
-
- /* A list item that is used for reverse lookup from the capability
- object to the client. Protected by the lock of the capability
- object. */
- struct _hurd_cap_list_item client_item;
-
- /* A flag that indicates if this capability is dead (revoked). Note
- that CAP_OBJ is still valid until all internal references have
- been removed. */
- unsigned int dead : 1;
-
- /* The number of internal references. These are references taken by
- the server for its own purpose. In fact, there is one such
- reference for all outstanding external references (if the dead
- flag is not set), and one for each pending RPC that uses this
- capability. If this reference counter drops to zero, the one
- real capability object reference held by this capability entry is
- released, and CAP_OBJ becomes invalid. */
- unsigned int internal_refs : 15;
-
- /* The number of external references. These are references granted
- to the user. For all these references, one internal reference is
- taken, unless the DEAD flag is set. */
- unsigned int external_refs : 16;
-};
-typedef struct _hurd_cap_obj_entry *_hurd_cap_obj_entry_t;
-
-
-/* The global slab for all capability entries. */
-extern struct hurd_slab_space _hurd_cap_obj_entry_space
- __attribute__((visibility("hidden")));
-
-/* Copy out a capability for the capability OBJ to the user CLIENT.
- Returns the capability ID (valid only for this user) in *R_ID, or
- an error. OBJ must be locked. */
-error_t _hurd_cap_obj_copy_out (hurd_cap_obj_t obj, hurd_cap_bucket_t bucket,
- _hurd_cap_client_t client, _hurd_cap_id_t *r_id)
- __attribute__((visibility("hidden")));
-
-
-/* Client connections. */
-
-
-/* Instances of the following data type are pointed to by the client
- table of a bucket. Its members are protected by the same lock as
- the table. The data type holds all the information about a client
- connection. */
-struct _hurd_cap_client
-{
- /* A flag that indicates if this capability client is dead. This
- data structure is valid until all references have been removed,
- though. Note that because there is one reference for the task
- info capability, this means that CLIENT is valid until a task
- death notification has been processed for this client. Protected
- by the containing bucket's lock LOCK. */
- unsigned int dead : 1;
-
- /* Reference counter. A reference is held if the client is live
- (and removed by the task death handler). One reference is held
- by each pending RPC. Temporarily, additional references may be
- held by RPCs that have just started, but they will rip themselves
- when they see the DEAD flag. Protected by the containing
- bucket's lock LOCK. */
- unsigned int refs : 31;
-
- /* The task ID of the client. */
- hurd_task_id_t task_id;
-
- /* The index of the client in the client table of the bucket.
- This is here so that we can hash for the address of this struct
- in the clients_reverse hash of the bucket, and still get the
- index number. This allows us to use a location pointer for
- removal (locp) for fast hash removal. */
- _hurd_cap_client_id_t id;
-
- /* The location pointer for fast removal from the reverse lookup
- hash BUCKET->clients_reverse. This is protected by the bucket
- lock. */
- hurd_ihash_locp_t locp;
-
- /* The lock protecting all the following members. Client locks can
- be taken while capability object locks are held! This is very
- important when copying or removing capabilities. On the other
- hand, this means you are not allowed to lock cabaility objects
- when holding a client lock. */
- pthread_mutex_t lock;
-
- /* The state of the client. If this is _HURD_CAP_STATE_GREEN, you
- can process RPCs for this client. Otherwise, you should drop
- RPCs for this client. If this is _HURD_CAP_STATE_YELLOW, and you
- are the last pending_rpc to finish, you have to broadcast the
- client_cond of the bucket. */
- enum _hurd_cap_state state;
-
- /* The current waiter thread. This is only valid if state is
- _HURD_CAP_STATE_YELLOW. Used by _hurd_cap_client_cond_busy (). */
- pthread_t cond_waiter;
-
- /* The pending RPC list. Each RPC worker thread should add itself
- to this list, so it can be cancelled by the task death
- notification handler. */
- struct _hurd_cap_list_item *pending_rpcs;
-
- /* The _hurd_cap_id_t to _hurd_cap_obj_entry_t mapping. */
- struct hurd_table caps;
-
- /* Reverse lookup from hurd_cap_obj_t to _hurd_cap_obj_entry_t. */
- struct hurd_ihash caps_reverse;
-};
-
-
-/* The global slab space for all capability clients. */
-extern struct hurd_slab_space _hurd_cap_client_space
- __attribute__((visibility("hidden")));
-
-
-/* Look up the client with the task ID TASK in the class CLASS, and
- return it in R_CLIENT, with one additional reference. If it is not
- found, create it. */
-error_t _hurd_cap_client_create (hurd_cap_bucket_t bucket,
- hurd_task_id_t task_id,
- _hurd_cap_client_t *r_client)
- __attribute__((visibility("hidden")));
-
-
-/* Deallocate the connection client CLIENT. */
-void _hurd_cap_client_dealloc (hurd_cap_bucket_t bucket,
- _hurd_cap_client_t client)
- __attribute__((visibility("hidden")));
-
-
-/* Release a reference for the client with the ID IDX in class
- CLASS. */
-void _hurd_cap_client_release (hurd_cap_bucket_t bucket,
- _hurd_cap_client_id_t idx)
- __attribute__((visibility("hidden")));
-
-
-/* Inhibit all RPCs on the capability client CLIENT (which must not be
- locked) in the bucket BUCKET. You _must_ follow up with a
- hurd_cap_client_resume operation, and hold at least one reference
- to the object continuously until you did so. */
-error_t _hurd_cap_client_inhibit (hurd_cap_bucket_t bucket,
- _hurd_cap_client_t client)
- __attribute__((visibility("hidden")));
-
-
-/* Resume RPCs on the capability client CLIENT in the bucket BUCKET
- and wake-up all waiters. */
-void _hurd_cap_client_resume (hurd_cap_bucket_t bucket,
- _hurd_cap_client_t client)
- __attribute__((visibility("hidden")));
-
-
-/* End RPCs on the capability client CLIENT in the bucket BUCKET and
- wake-up all waiters. */
-void _hurd_cap_client_end (hurd_cap_bucket_t bucket,
- _hurd_cap_client_t client)
- __attribute__((visibility("hidden")));
-
-
-/* Buckets are a set of capabilities, on which RPCs are managed
- collectively. */
-
-struct _hurd_cap_bucket
-{
- /* Client management. */
-
- /* The following condition is used in conjunction with the state
- predicate of the client associated with the the currently
- processed death task notification. */
- pthread_cond_t client_cond;
-
- /* The following mutex is associated with the client_cond condition.
- Note that this mutex does _not_ protect the predicate of the
- condition: The predicate is the state of the respective client
- and that is protected by the lock of each client itself. In
- fact, this mutex has no purpose but to serve the condition. The
- reason is that this way we avoid lock contention when checking
- the state of a client.
-
- So, first you lock the client structure. You have to do this
- anyway. Then you check the state. If the state is
- _HURD_CAP_STATE_GREEN, you can unlock the client and continue
- normally. However, if the state is _HURD_CAP_STATE_YELLOW, you
- have to unlock the client, lock this mutex, then lock the client
- again and reinvestigate the state. If necessary (ie, you are the
- last RPC except the waiter) you can set the state to
- _HURD_CAP_STATE_RED and broadcast the condition. This sounds
- cumbersome, but the important part is that the common case, the
- _HURD_CAP_STATE_GREEN, is handled quickly and without class-wide
- lock contention. */
- pthread_mutex_t client_cond_lock;
-
- /* The following entry is protected by hurd_task_death_notify_lock. */
- struct hurd_task_death_notify_list_item client_death_notify;
-
-
- /* Bucket management. */
-
- /* The following members are protected by this lock. */
- pthread_mutex_t lock;
-
- /* The manager thread for this capability class. */
- pthread_t manager;
-
- /* True if MANAGER is valid and the bucket is managed. */
- bool is_managed;
-
- /* If this is true, then the manager is waiting for the free worker
- list to become empty (at shutdown) or filled (else). The first
- worker thread to notice that the condition is fulfilled now
- should broadcast the condition. */
- bool is_manager_waiting;
-
- /* The state of the bucket. */
- _hurd_cap_state_t state;
-
- /* The condition used to wait on state changes and changes in the
- worker thread list. */
- pthread_cond_t cond;
-
- /* The thread waiting for the RPCs to be inhibited. */
- pthread_t cond_waiter;
-
- /* The number of capabilities. If this is not 0, then there are
- active users. */
- unsigned int nr_caps;
-
- /* The pending RPCs in this bucket. */
- _hurd_cap_list_item_t pending_rpcs;
-
- /* The waiting RPCs in this bucket. */
- _hurd_cap_list_item_t waiting_rpcs;
-
- /* The free worker threads in this bucket. */
- _hurd_cap_list_item_t free_worker;
-
- /* A hash from l4_thread_id_t to _hurd_cap_list_item_t (the list
- items in PENDING_RPCs). This is used to limit each client thread
- to just one RPC at one time. */
- struct hurd_ihash senders;
-
- /* Mapping from hurd_cap_client_id_t to _hurd_cap_client_t. */
- struct hurd_table clients;
-
- /* Reverse lookup from hurd_task_id_t to _hurd_cap_client_t. */
- struct hurd_ihash clients_reverse;
-
- /* This is true if worker threads should be allocated
- asynchronously. */
- bool is_worker_alloc_async;
-
- /* If WORKER_ALLOC_ASYNC is true, this is the state of the worker
- thread allocation thread. If this is _HURD_CAP_STATE_GREEN, then
- a new thread should be allocated. If this is
- _HURD_CAP_STATE_YELLOW, the worker thread has allocated a new
- thread, and is currently waiting for the thread to complete its
- startup. If this is _HURD_CAP_STATE_RED, the new worker thread
- has completed its startup (if one was started) and no new thread
- will be allocated. */
- _hurd_cap_state_t worker_alloc_state;
-
- /* If WORKER_ALLOC_ASYNC is true, this is the allocator thread. */
- pthread_t worker_alloc;
-};
-
-
-/* Return true if there are still outstanding RPCs in this bucket
- BUCKET, and fails if not. This is only valid if
- hurd_cap_bucket_inhibit is in progress (ie, if bucket->state is
- _HURD_CAP_STATE_YELLOW). BUCKET must be locked. */
-static inline int
-__attribute__((always_inline))
-_hurd_cap_bucket_cond_busy (hurd_cap_bucket_t bucket)
-{
- /* We have to remain in the state yellow until there are no pending
- RPC threads except maybe the waiter. */
- return bucket->pending_rpcs
- && (bucket->pending_rpcs->thread != bucket->cond_waiter
- || bucket->pending_rpcs->next);
-}
-
-
-/* Check if the inhibition state of the capability bucket BUCKET has
- to be changed. BUCKET must be locked. */
-static inline void
-__attribute__((always_inline))
-_hurd_cap_bucket_cond_check (hurd_cap_bucket_t bucket)
-{
- if (bucket->state == _HURD_CAP_STATE_YELLOW
- && !_hurd_cap_bucket_cond_busy (bucket))
- {
- bucket->state =_HURD_CAP_STATE_RED;
- pthread_cond_broadcast (&bucket->cond);
- }
-}
-
-
-/* Capability clients. */
-
-/* Return true if there are still outstanding RPCs in this capability
- client, and fails if not. CLIENT must be locked. This is only
- valid if hurd_cap_client_inhibit is in progress (ie, if
- client->state is _HURD_CAP_STATE_YELLOW). */
-static inline int
-__attribute__((always_inline))
-_hurd_cap_client_cond_busy (_hurd_cap_client_t client)
-{
- /* We have to remain in the state yellow until there are no pending
- RPC threads except maybe the waiter. */
- return client->pending_rpcs
- && (client->pending_rpcs->thread != client->cond_waiter
- || client->pending_rpcs->next);
-}
-
-
-/* Check if the inhibited state of the capability client CLIENT has to
- be changed. CLIENT must be locked. */
-static inline void
-__attribute__((always_inline))
-_hurd_cap_client_cond_check (hurd_cap_bucket_t bucket,
- _hurd_cap_client_t client)
-{
- if (client->state == _HURD_CAP_STATE_YELLOW
- && !_hurd_cap_client_cond_busy (client))
- {
- client->state = _HURD_CAP_STATE_RED;
- pthread_cond_broadcast (&bucket->client_cond);
- }
-}
-
-
-/* Capability classes. */
-
-/* Return true if there are still outstanding RPCs in this class, and
- fails if not. CAP_CLASS must be locked. This is only valid if
- hurd_cap_class_inhibit is in progress (ie, if cap_class->state is
- _HURD_CAP_STATE_YELLOW). */
-static inline int
-__attribute__((always_inline))
-_hurd_cap_class_cond_busy (hurd_cap_class_t cap_class)
-{
- /* We have to remain in the state yellow until there are no pending
- RPC threads except maybe the waiter. */
- return cap_class->pending_rpcs
- && (cap_class->pending_rpcs->thread != cap_class->cond_waiter
- || cap_class->pending_rpcs->next);
-}
-
-
-/* Check if the inhibition state of the capability class CAP_CLASS has
- to be changed. CAP_CLASS must be locked. */
-static inline void
-__attribute__((always_inline))
-_hurd_cap_class_cond_check (hurd_cap_class_t cap_class)
-{
- if (cap_class->state == _HURD_CAP_STATE_YELLOW
- && !_hurd_cap_class_cond_busy (cap_class))
- {
- cap_class->state = _HURD_CAP_STATE_RED;
- pthread_cond_broadcast (&cap_class->cond);
- }
-}
-
-
-/* Capability objects. */
-
-/* Return true if there are still outstanding RPCs in this capability
- object, and fails if not. OBJ must be locked. This is only valid
- if hurd_cap_obj_inhibit is in progress (ie, if cap_obj->state is
- _HURD_CAP_STATE_YELLOW). */
-static inline int
-__attribute__((always_inline))
-_hurd_cap_obj_cond_busy (hurd_cap_obj_t obj)
-{
- /* We have to remain in the state yellow until there are no pending
- RPC threads except maybe the waiter. */
- return obj->pending_rpcs
- && (obj->pending_rpcs->thread != obj->cond_waiter
- || obj->pending_rpcs->next);
-}
-
-
-/* Check if the inhibition state of the capability class CAP_CLASS has
- to be changed. CAP_CLASS must be locked. */
-static inline void
-__attribute__((always_inline))
-_hurd_cap_obj_cond_check (hurd_cap_obj_t obj)
-{
- if (obj->state == _HURD_CAP_STATE_YELLOW
- && !_hurd_cap_obj_cond_busy (obj))
- {
- obj->state = _HURD_CAP_STATE_RED;
- pthread_cond_broadcast (&obj->cap_class->cond);
- }
-}
-
-/* The following structure is used when using other capabilities in an
- RPC handler beside the one on which the RPC was invoked. */
-struct hurd_cap_ctx_cap_use
-{
- /* Private members. */
-
- _hurd_cap_obj_entry_t _obj_entry;
-
- /* The pending_rpc list item for the object's pending RPC list. */
- struct _hurd_cap_list_item _worker_obj;
-
- /* The pending_rpc list item for the object class' pending RPC list. */
- struct _hurd_cap_list_item _worker_class;
-};
-
-
-#endif /* _HURD_CAP_SERVER_INTERN_H */
diff --git a/libhurd-cap-server/cap-server.h b/libhurd-cap-server/cap-server.h
deleted file mode 100644
index e12e986..0000000
--- a/libhurd-cap-server/cap-server.h
+++ /dev/null
@@ -1,573 +0,0 @@
-/* cap-server.h - Server interface to the Hurd capability library.
- 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_CAP_SERVER_H
-#define _HURD_CAP_SERVER_H 1
-
-#include <stdbool.h>
-#include <errno.h>
-#include <pthread.h>
-
-/* FIXME: This is not a public header file! So we may have to ship
- a <hurd/atomic.h>. */
-#include <atomic.h>
-
-#include <hurd/slab.h>
-#include <hurd/types.h>
-
-
-/* Internal declarations. */
-
-/* This is a simple list item, used to maintain lists of pending RPC
- worker threads in a capability class, client, or object. */
-struct _hurd_cap_list_item;
-typedef struct _hurd_cap_list_item *_hurd_cap_list_item_t;
-
-
-/* The state of a capability class, client, or object. */
-typedef enum _hurd_cap_state
- {
- _HURD_CAP_STATE_GREEN,
- _HURD_CAP_STATE_YELLOW,
- _HURD_CAP_STATE_RED,
- _HURD_CAP_STATE_BLACK
- }
-_hurd_cap_state_t;
-
-
-/* Public interface. */
-
-/* Forward declarations. */
-struct _hurd_cap_bucket;
-typedef struct _hurd_cap_bucket *hurd_cap_bucket_t;
-struct _hurd_cap_client;
-typedef struct _hurd_cap_client *_hurd_cap_client_t;
-struct hurd_cap_class;
-typedef struct hurd_cap_class *hurd_cap_class_t;
-struct hurd_cap_obj;
-typedef struct hurd_cap_obj *hurd_cap_obj_t;
-
-
-typedef error_t (*hurd_cap_obj_init_t) (hurd_cap_class_t cap_class,
- hurd_cap_obj_t obj);
-typedef error_t (*hurd_cap_obj_alloc_t) (hurd_cap_class_t cap_class,
- hurd_cap_obj_t obj);
-typedef void (*hurd_cap_obj_reinit_t) (hurd_cap_class_t cap_class,
- hurd_cap_obj_t obj);
-typedef void (*hurd_cap_obj_destroy_t) (hurd_cap_class_t cap_class,
- hurd_cap_obj_t obj);
-
-
-/* The RPC context contains various information for the RPC handler
- and the support functions. */
-struct hurd_cap_rpc_context
-{
- /* Public members. */
-
- /* The task which contained the sender of the message. */
- hurd_task_id_t sender;
-
- /* The bucket through which the message was received. */
- hurd_cap_bucket_t bucket;
-
- /* The capability object on which the RPC was invoked. */
- hurd_cap_obj_t obj;
-
- /* The capability handle on which the RPC was invoked. */
- hurd_cap_handle_t handle;
-
- /* Private members. */
-
- /* The sender of the message. */
- l4_thread_id_t from;
-
- /* The client corresponding to FROM. */
- _hurd_cap_client_t client;
-
- /* The message. */
- l4_msg_t msg;
-};
-typedef struct hurd_cap_rpc_context *hurd_cap_rpc_context_t;
-
-/* FIXME: Add documentation. */
-typedef error_t (*hurd_cap_class_demuxer_t) (hurd_cap_rpc_context_t ctx);
-
-
-/* A capability class is a group of capability objects of the same
- type. */
-struct hurd_cap_class
-{
- /* Capability object management for the class. */
-
- /* The following callbacks are used to adjust the state of an object
- during its lifetime:
-
- 1. Object is constructed in the cache OBJ_INIT
- 2.1. Object is instantiated and removed from the free list OBJ_ALLOC
- 2.2. Object is deallocated and put back on the free list OBJ_REINIT
- 3. Object is destroyed and removed from the cache OBJ_DESTROY
-
- Note that step 2 can occur several times, or not at all.
- This is the state diagram for each object:
-
- (START) --(1.)-> initialized --(3.)--> destroyed (END)
- | ^
- | |
- (2.1.) (2.2.)
- | |
- v |
- allocated
-
- Note that OBJ_INIT will be called in bursts for pre-allocation of
- several objects. */
-
- /* This callback is invoked whenever a new object is pre-allocated
- in the cache. It is usually called in bursts when a new slab
- page is allocated. You can put all initialization in it that
- should be cached. */
- hurd_cap_obj_init_t obj_init;
-
- /* This callback is called whenever an object in the cache is going
- to be instantiated and used. You can put further initialization
- in it that is not suitable for caching (for example, because it
- can not be safely reinitialized by OBJ_REINIT). If OBJ_ALLOC
- fails, then it must leave the object in its initialized
- state! */
- hurd_cap_obj_alloc_t obj_alloc;
-
- /* This callback is invoked whenever a used object is deallocated
- and returned to the cache. It should revert the used object to
- its initialized state, this means as if OBJ_INIT had been called
- on a freshly constructed object. This also means that you have
- to deallocate all resources that have been allocated by
- OBJ_ALLOC. Note that this function can not fail. Initialization
- that can not be safely (error-free) reverted to its original
- state must be put into the OBJ_ALLOC callback, rather than in the
- OBJ_INIT callback. */
- hurd_cap_obj_reinit_t obj_reinit;
-
- /* This callback is invoked whenever an initialized, but unused
- object is removed from the cache and destroyed. You should
- release all resources that have been allocated for this object by
- a previous OBJ_INIT invocation. */
- hurd_cap_obj_destroy_t obj_destroy;
-
- /* The slab space containing the capabilities in this class. */
- struct hurd_slab_space obj_space;
-
- /* The following condition is used in conjunction with the state
- predicate of a capability object. */
- pthread_cond_t obj_cond;
-
- /* The following mutex is associated with the obj_cond
- condition. Note that this mutex does _not_ protect the predicate
- of the condition: The predicate is the state of the respective
- client and that is protected by the lock of each capability
- object itself. */
- pthread_mutex_t obj_cond_lock;
-
-
- /* The class management. */
-
- /* The demuxer for this class. */
- hurd_cap_class_demuxer_t demuxer;
-
- /* The lock protecting all the following members. */
- pthread_mutex_t lock;
-
- /* The state of the class. */
- _hurd_cap_state_t state;
-
- /* The condition used for waiting on state changes. The associated
- mutex is LOCK. */
- pthread_cond_t cond;
-
- /* The current waiter thread. This is only valid if state is
- _HURD_CAP_STATE_YELLOW. Used by _hurd_cap_class_cond_busy (). */
- pthread_t cond_waiter;
-
- /* The pending RPC worker threads for this class. */
- _hurd_cap_list_item_t pending_rpcs;
-};
-
-
-/* Server-side objects that are accessible via capabilities. */
-struct hurd_cap_obj
-{
- /* The class which contains this capability. */
- hurd_cap_class_t cap_class;
-
- /* The lock protecting all the members of the capability object. */
- pthread_mutex_t lock;
-
- /* The reference counter for this object. */
- uatomic32_t refs;
-
- /* The state of the capability object.
-
- If STATE is _HURD_CAP_STATE_GREEN, you can use the capability
- object. Otherwise, you must wait on the condition
- CAP_CLASS->OBJ_COND for it return to _HURD_CAP_STATE_GREEN.
-
- If the state is _HURD_CAP_STATE_YELLOW, a thread wants the state
- to be _HURD_CAP_STATE_RED (and it has canceled all other pending
- RPC threads on this object). The last worker thread for this
- capability object (other than the thread waiting for the
- condition to become _HURD_CAP_STATE_RED) must broadcast the
- obj_state_cond condition.
-
- Every worker thread that blocks on the capability object state
- until it reverts to _HURD_CAP_STATE_GREEN must perform a
- reauthentication when it is unblocked (ie, verify that the client
- still has access to the capability object), in case the
- capability of the client for this object was revoked in the
- meantime.
-
- _HURD_CAP_STATE_BLACK is not used for capability objects. */
- _hurd_cap_state_t state;
-
- /* The pending RPC worker threads for this capability object. */
- _hurd_cap_list_item_t pending_rpcs;
-
- /* The current waiter thread. This is only valid if STATE is
- _HURD_CAP_STATE_YELLOW. Used by _hurd_cap_obj_cond_busy (). */
- pthread_t cond_waiter;
-
- /* The list items in the capability entries of the clients using
- this capability. */
- _hurd_cap_list_item_t clients;
-};
-
-
-/* Operations on capability classes. */
-
-/* Create a new capability class for objects with the size SIZE and
- alignment requirement ALIGNMENT (which must be a power of 2).
-
- The callback OBJ_INIT is used whenever a capability object in this
- class is created. The callback OBJ_REINIT is used whenever a
- capability object in this class is deallocated and returned to the
- slab. OBJ_REINIT should bring back a capability object that is not
- used anymore into the same state as OBJ_INIT does for a freshly
- allocated object. OBJ_DESTROY should deallocate all resources for
- this capablity object. Note that OBJ_REINIT can not fail: If you
- have resources that can not safely be restored into their initial
- state, you cannot use OBJ_INIT to allocate them. Furthermore, note
- that OBJ_INIT will usually be called in bursts for advanced
- allocation.
-
- The new capability class is returned in R_CLASS. If the creation
- fails, an error value will be returned. */
-error_t hurd_cap_class_create_untyped (size_t size, size_t alignment,
- hurd_cap_obj_init_t obj_init,
- hurd_cap_obj_alloc_t obj_alloc,
- hurd_cap_obj_reinit_t obj_reinit,
- hurd_cap_obj_destroy_t obj_destroy,
- hurd_cap_class_demuxer_t demuxer,
- hurd_cap_class_t *r_class);
-
-/* Define a capability class for the pointer type TYPE. */
-#define hurd_cap_class_create(type,init,alloc,reinit,destroy,demuxer,r_class) \
- hurd_cap_class_create_untyped (({ type t; sizeof (*t); }), \
- ({ type t; __alignof__ (*t); }), \
- init, alloc, reinit, destroy, demuxer, \
- r_class);
-
-
-/* Destroy the capability class CAP_CLASS and release all associated
- resources. Note that this is only allowed if there are no
- capability objects in use, and if the capability class is not used
- by a capability server. This function assumes that the class was
- created with hurd_cap_class_create. */
-error_t hurd_cap_class_free (hurd_cap_class_t cap_class);
-
-
-/* Same as hurd_cap_class_create, but doesn't allocate the storage for
- CAP_CLASS. Instead, you have to provide it. */
-error_t hurd_cap_class_init_untyped (hurd_cap_class_t cap_class,
- size_t size, size_t alignment,
- hurd_cap_obj_init_t obj_init,
- hurd_cap_obj_alloc_t obj_alloc,
- hurd_cap_obj_reinit_t obj_reinit,
- hurd_cap_obj_destroy_t obj_destroy,
- hurd_cap_class_demuxer_t demuxer);
-
-/* Define a capability class for the pointer type TYPE. */
-#define hurd_cap_class_init(cclass,type,init,alloc,reinit,destroy,demuxer) \
- hurd_cap_class_init_untyped (cclass, ({ type t; sizeof (*t); }), \
- ({ type t; __alignof__ (*t); }), \
- init, alloc, reinit, destroy, demuxer);
-
-
-/* Destroy the capability class CAP_CLASS and release all associated
- resources. Note that this is only allowed if there are no
- capability objects in use, and if the capability class is not used
- by a capability server. This function assumes that the class has
- been initialized with hurd_cap_class_init. */
-error_t hurd_cap_class_destroy (hurd_cap_class_t cap_class);
-
-
-/* Allocate a new capability object in the class CAP_CLASS. The new
- capability object is locked and has one reference. It will be
- returned in R_OBJ. If the allocation fails, an error value will be
- returned. The object will be destroyed as soon as its last
- reference is dropped. */
-error_t hurd_cap_class_alloc (hurd_cap_class_t cap_class,
- hurd_cap_obj_t *r_obj);
-
-
-/* Get the offset of the user object following a capability.
- ALIGNMENT is the alignment requirements of the user object as
- supplied to hurd_cap_class_init, hurd_cap_class_init_untyped,
- hurd_cap_class_create or hurd_cap_class_create_untyped. */
-static inline size_t
-__attribute__((__always_inline__))
-hurd_cap_obj_user_offset (size_t alignment)
-{
- size_t offset = sizeof (struct hurd_cap_obj);
- size_t rest = sizeof (struct hurd_cap_obj) % alignment;
-
- if (rest)
- offset += alignment - rest;
-
- return offset;
-}
-
-
-/* Find the user object of the pointer type TYPE after the capability
- object OBJ. Note that in conjunction with the hurd_cap_obj_to_user
- macro below, all of this can and will be computed at compile time,
- if optimization is enabled. OBJ already fulfills the alignment
- requirement ALIGNMENT. */
-static inline void *
-__attribute__((__always_inline__))
-hurd_cap_obj_to_user_untyped (hurd_cap_obj_t obj, size_t alignment)
-{
- uintptr_t obj_addr = (uintptr_t) obj;
-
- obj_addr += hurd_cap_obj_user_offset (alignment);
-
- return (void *) obj_addr;
-}
-
-#define hurd_cap_obj_to_user(type,obj) \
- ((type) hurd_cap_obj_to_user_untyped (obj, ({ type t; __alignof__ (*t); })))
-
-
-/* Find the hurd cap object before the user object OBJ of the pointer
- type TYPE. Note that in conjunction with the hurd_cap_obj_from_user
- macro below, all of this can and will be computed at compile time,
- if optimization is enabled. OBJ already fulfills the alignment
- requirement ALIGNMENT. */
-static inline hurd_cap_obj_t
-__attribute__((__always_inline__))
-hurd_cap_obj_from_user_untyped (void *obj, size_t alignment)
-{
- uintptr_t obj_addr = (uintptr_t) obj;
-
- obj_addr -= hurd_cap_obj_user_offset (alignment);
-
- return (hurd_cap_obj_t) obj_addr;
-}
-
-#define hurd_cap_obj_from_user(type,obj) \
- hurd_cap_obj_from_user_untyped (obj, ({ type t; __alignof__ (*t); }))
-
-
-/* Inhibit all RPCs on the capability class CAP_CLASS (which must not
- be locked). You _must_ follow up with a hurd_cap_class_resume
- operation, and hold at least one reference to the object
- continuously until you did so. */
-error_t hurd_cap_class_inhibit (hurd_cap_class_t cap_class);
-
-
-/* Resume RPCs on the class CAP_CLASS and wake-up all waiters. */
-void hurd_cap_class_resume (hurd_cap_class_t cap_class);
-
-
-/* Operations on capability objects. */
-
-/* Lock the object OBJ. */
-static inline void
-hurd_cap_obj_lock (hurd_cap_obj_t obj)
-{
- pthread_mutex_lock (&obj->lock);
-}
-
-/* Unlock the object OBJ, which must be locked. */
-static inline void
-hurd_cap_obj_unlock (hurd_cap_obj_t obj)
-{
- pthread_mutex_unlock (&obj->lock);
-}
-
-
-/* Add a reference to the capability object OBJ. */
-static inline void
-hurd_cap_obj_ref (hurd_cap_obj_t obj)
-{
- atomic_increment (&obj->refs);
-}
-
-
-/* Remove one reference for the capability object OBJ, which must be
- locked. Note that the caller must have at least two references for
- this capability object when using this function. If this reference
- is potentially the last reference (i.e. the caller does not hold
- either directly or indirectly another reference to OBJ),
- hurd_cap_obj_drop must be used instead. */
-static inline void
-hurd_cap_obj_rele (hurd_cap_obj_t obj)
-{
- atomic_decrement (&obj->refs);
-}
-
-
-/* Remove one reference for the capability object OBJ, which must be
- locked, and will be unlocked when the function returns. If this
- was the last user of this object, the object is deallocated. */
-void hurd_cap_obj_drop (hurd_cap_obj_t obj);
-
-
-/* Inhibit all RPCs on the capability object OBJ (which must not be
- locked). You _must_ follow up with a hurd_cap_obj_resume
- operation, and hold at least one reference to the object
- continuously until you did so. */
-error_t hurd_cap_obj_inhibit (hurd_cap_obj_t obj);
-
-
-/* Resume RPCs on the capability object OBJ and wake-up all
- waiters. */
-void hurd_cap_obj_resume (hurd_cap_obj_t obj);
-
-
-/* Buckets are a set of capabilities, on which RPCs are managed
- collectively. */
-
-/* Create a new bucket and return it in R_BUCKET. */
-error_t hurd_cap_bucket_create (hurd_cap_bucket_t *r_bucket);
-
-
-/* Free the bucket BUCKET, which must not be used. */
-void hurd_cap_bucket_free (hurd_cap_bucket_t bucket);
-
-
-/* Copy out a capability for the capability OBJ to the client with the
- task ID TASK_ID. Returns the capability (valid only for this user)
- in *R_CAP, or an error. It is not safe to call this from outside
- an RPC on OBJ while the manager is running. */
-error_t hurd_cap_bucket_inject (hurd_cap_bucket_t bucket, hurd_cap_obj_t obj,
- hurd_task_id_t task_id,
- hurd_cap_handle_t *r_cap);
-
-
-/* If ASYNC is true, allocate worker threads asynchronously whenever
- the number of worker threads is exhausted. This is only actually
- required for physmem (the physical memory server), to allow to
- break out of a dead-lock between physmem and the task server. It
- should be unnecessary for any other server.
-
- The default is to false, which means that worker threads are
- allocated synchronously by the manager thread.
-
- This function should be called before the manager is started with
- hurd_cap_bucket_manage_mt. It is only used for the multi-threaded
- RPC manager. */
-error_t hurd_cap_bucket_worker_alloc (hurd_cap_bucket_t bucket, bool async);
-
-
-/* Start managing RPCs on the bucket BUCKET. The ROOT capability
- object, which must be unlocked and have one reference throughout
- the whole time this function runs, is used for bootstrapping client
- connections. The GLOBAL_TIMEOUT parameter specifies the number of
- seconds until the manager times out (if there are no active users
- of capability objects in precious classes). The WORKER_TIMEOUT
- parameter specifies the number of seconds until each worker thread
- times out (if there are no RPCs processed by the worker thread).
-
- If this returns ECANCELED, then hurd_cap_bucket_end was called with
- the force flag being true while there were still active users. If
- this returns without any error, then the timeout expired, or
- hurd_cap_bucket_end was called without active users of capability
- objects in precious classes. */
-error_t hurd_cap_bucket_manage_mt (hurd_cap_bucket_t bucket,
- hurd_cap_obj_t root,
- unsigned int global_timeout,
- unsigned int worker_timeout);
-
-
-/* Inhibit all RPCs on the capability bucket BUCKET (which must not be
- locked). You _must_ follow up with a hurd_cap_bucket_resume (or
- hurd_cap_bucket_end) operation. */
-error_t hurd_cap_bucket_inhibit (hurd_cap_bucket_t bucket);
-
-
-/* Resume RPCs on the class CAP_CLASS and wake-up all waiters. */
-void hurd_cap_bucket_resume (hurd_cap_bucket_t bucket);
-
-
-/* Exit from the server loop of the managed capability bucket BUCKET.
- This will only succeed if there are no active users, or if the
- FORCE flag is set (otherwise it will fail with EBUSY). The bucket
- must be inhibited. */
-error_t hurd_cap_bucket_end (hurd_cap_bucket_t bucket, bool force);
-
-
-/* If you want to use other capabilities in an RPC handler beside the
- one on which the RPC was invoked, you need to make sure that
- inhibition works on those other capabilities and cancel your
- operation. For this, the following interfaces are provided. */
-
-/* Forward. */
-struct hurd_cap_ctx_cap_use;
-
-/* Return the number of bytes required for a hurd_cap_ctx_cap_use
- structure. */
-size_t hurd_cap_ctx_size (void) __attribute__ ((const));
-
-/* The calling thread wishes to execute an RPC on the the handle
- HANDLE. The calling thread must already be registered as executing
- an RPC. RPC_CTX is the cooresponding RPC context. The function
- uses the structure CAP_USE, which must point to the number of bytes
- returned by hurd_cap_ctx_size, to store data required by
- hurd_cap_ctx_end_cap_use. The capability object corresponding to
- HANDLE is locked and returned in *OBJP.
-
- Returns EINVAL if the capability handle is invalid for the client.
-
- Returns ENOENT if there is no object associated with handle HANDLE.
-
- Returns EBAD if the capability is dead.
-
- Returns EDOM if the object associated with HANDLE is not in class
- REQUIRED_CLASS. If no type check is required, it will be skipped
- if REQURIED_CLASS is NULL. */
-error_t hurd_cap_ctx_start_cap_use (hurd_cap_rpc_context_t rpc_ctx,
- hurd_cap_handle_t handle,
- hurd_cap_class_t required_class,
- struct hurd_cap_ctx_cap_use *cap_use,
- hurd_cap_obj_t *objp);
-
-/* End the use of the object CAP_USE->OBJ, which must be locked. */
-void hurd_cap_ctx_end_cap_use (hurd_cap_rpc_context_t rpc_ctx,
- struct hurd_cap_ctx_cap_use *cap_use);
-
-#endif /* _HURD_CAP_SERVER_H */
diff --git a/libhurd-cap-server/class-alloc.c b/libhurd-cap-server/class-alloc.c
deleted file mode 100644
index b57ca97..0000000
--- a/libhurd-cap-server/class-alloc.c
+++ /dev/null
@@ -1,64 +0,0 @@
-/* class-alloc.c - Allocate a capability object.
- 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. */
-
-#if HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <errno.h>
-
-#include <hurd/slab.h>
-#include <hurd/cap-server.h>
-
-
-/* Allocate a new capability object in the class CAP_CLASS. The new
- capability object is locked and has one reference. It will be
- returned in R_OBJ. If the allocation fails, an error value will be
- returned. */
-error_t
-hurd_cap_class_alloc (hurd_cap_class_t cap_class, hurd_cap_obj_t *r_obj)
-{
- error_t err;
- void *new_obj;
- hurd_cap_obj_t obj;
-
- err = hurd_slab_alloc (&cap_class->obj_space, &new_obj);
- if (err)
- return err;
- obj = new_obj;
-
- /* Let the user do their extra initialization. */
- if (cap_class->obj_alloc)
- {
- err = (*cap_class->obj_alloc) (cap_class, obj);
- if (err)
- {
- hurd_slab_dealloc (&cap_class->obj_space, obj);
- return err;
- }
- }
-
- /* Now take the lock. */
- hurd_cap_obj_lock (obj);
-
- *r_obj = obj;
- return 0;
-}
diff --git a/libhurd-cap-server/class-create.c b/libhurd-cap-server/class-create.c
deleted file mode 100644
index 2f4c16a..0000000
--- a/libhurd-cap-server/class-create.c
+++ /dev/null
@@ -1,75 +0,0 @@
-/* class-create.c - Create a capability class.
- 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. */
-
-#if HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <errno.h>
-#include <stdlib.h>
-
-#include <hurd/cap-server.h>
-
-
-/* Create a new capability class for objects allocating SIZE bytes for
- the user object with alignment ALIGNMENT (i.e. size does NOT
- include the struct hurd_cap_obj which is placed at the beginning of
- each capability object).
-
- The callback OBJ_INIT is used whenever a capability object in this
- class is created. The callback OBJ_REINIT is used whenever a
- capability object in this class is deallocated and returned to the
- slab. OBJ_REINIT should return a capability object that is not
- used anymore into the same state as OBJ_INIT does for a freshly
- allocated object. OBJ_DESTROY should deallocate all resources for
- this capablity object. Note that if OBJ_INIT or OBJ_REINIT fails,
- the object is considered to be fully destroyed. No extra call to
- OBJ_DESTROY will be made for such objects.
-
- The new capability class is returned in R_CLASS. If the creation
- fails, an error value will be returned. */
-error_t
-hurd_cap_class_create_untyped (size_t size, size_t alignment,
- hurd_cap_obj_init_t obj_init,
- hurd_cap_obj_alloc_t obj_alloc,
- hurd_cap_obj_reinit_t obj_reinit,
- hurd_cap_obj_destroy_t obj_destroy,
- hurd_cap_class_demuxer_t demuxer,
- hurd_cap_class_t *r_class)
-{
- error_t err;
- hurd_cap_class_t cap_class = malloc (sizeof (struct hurd_cap_class));
-
- if (!cap_class)
- return errno;
-
- err = hurd_cap_class_init_untyped (cap_class, size, alignment, obj_init,
- obj_alloc, obj_reinit, obj_destroy,
- demuxer);
- if (err)
- {
- free (cap_class);
- return err;
- }
-
- *r_class = cap_class;
- return 0;
-}
diff --git a/libhurd-cap-server/class-destroy.c b/libhurd-cap-server/class-destroy.c
deleted file mode 100644
index 116d99a..0000000
--- a/libhurd-cap-server/class-destroy.c
+++ /dev/null
@@ -1,58 +0,0 @@
-/* class-destroy.c - Destroy a capability class.
- 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. */
-
-#if HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <errno.h>
-#include <pthread.h>
-
-#include <hurd/cap-server.h>
-
-
-/* Destroy the capability class CAP_CLASS and release all associated
- resources. Note that this is only allowed if there are no
- capability objects in use, and if the capability class is not used
- by a capability server. This function assumes that the class has
- been initialized with hurd_cap_class_init. */
-error_t
-hurd_cap_class_destroy (hurd_cap_class_t cap_class)
-{
- error_t err = 0;
-
- /* FIXME: This function needs to be revised. We need to take the
- locks, and if only for memory synchronization. */
-
- /* This will fail if there are still allocated capability
- objects. */
- err = hurd_slab_destroy (&cap_class->obj_space);
- if (err)
- return err;
-
- /* At this point, destruction will succeed. */
- pthread_cond_destroy (&cap_class->cond);
- pthread_mutex_destroy (&cap_class->lock);
- pthread_mutex_destroy (&cap_class->obj_cond_lock);
- pthread_cond_destroy (&cap_class->obj_cond);
-
- return 0;
-}
diff --git a/libhurd-cap-server/class-free.c b/libhurd-cap-server/class-free.c
deleted file mode 100644
index 6c5c0be..0000000
--- a/libhurd-cap-server/class-free.c
+++ /dev/null
@@ -1,48 +0,0 @@
-/* class-free.c - Free a capability class.
- 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. */
-
-#if HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <errno.h>
-#include <stdlib.h>
-
-#include <hurd/cap-server.h>
-
-
-/* Destroy the capability class CAP_CLASS and release all associated
- resources. Note that this is only allowed if there are no
- capability objects in use, and if the capability class is not used
- by a capability server. This function assumes that the class was
- created with hurd_cap_class_create. */
-error_t
-hurd_cap_class_free (hurd_cap_class_t cap_class)
-{
- error_t err;
-
- err = hurd_cap_class_destroy (cap_class);
- if (err)
- return err;
-
- free (cap_class);
- return 0;
-}
diff --git a/libhurd-cap-server/class-inhibit.c b/libhurd-cap-server/class-inhibit.c
deleted file mode 100644
index ea2a663..0000000
--- a/libhurd-cap-server/class-inhibit.c
+++ /dev/null
@@ -1,114 +0,0 @@
-/* class-inhibit.c - Inhibit RPCs on a capability class.
- 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. */
-
-#if HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <errno.h>
-#include <pthread.h>
-#include <stdlib.h>
-
-#include "cap-server-intern.h"
-
-
-/* Inhibit all RPCs on the capability class CAP_CLASS (which must not
- be locked). You _must_ follow up with a hurd_cap_class_resume
- operation, and hold at least one reference to the object
- continuously until you did so. */
-error_t
-hurd_cap_class_inhibit (hurd_cap_class_t cap_class)
-{
- error_t err;
-
- pthread_mutex_lock (&cap_class->lock);
-
- /* First wait until any other inhibitor has resumed the class. If
- this function is called within an RPC, we are going to be
- canceled anyway. Otherwise, it ensures that class inhibitions
- are fully serialized (per class). */
- while (cap_class->state != _HURD_CAP_STATE_GREEN)
- {
- err = hurd_cond_wait (&cap_class->cond, &cap_class->lock);
- if (err)
- {
- /* We have been canceled. */
- pthread_mutex_unlock (&cap_class->lock);
- return err;
- }
- }
-
- /* Now it is our turn to inhibit the class. */
- cap_class->cond_waiter = pthread_self ();
-
- if (_hurd_cap_class_cond_busy (cap_class))
- {
- _hurd_cap_list_item_t pending_rpc = cap_class->pending_rpcs;
-
- /* There are still pending RPCs (beside us). Cancel them. */
- while (pending_rpc)
- {
- if (pending_rpc->thread != cap_class->cond_waiter)
- pthread_cancel (pending_rpc->thread);
- pending_rpc = pending_rpc->next;
- }
-
- /* Indicate that we would like to know when they have gone. */
- cap_class->state = _HURD_CAP_STATE_YELLOW;
-
- /* The last one will shut the door. */
- do
- {
- err = hurd_cond_wait (&cap_class->cond, &cap_class->lock);
- if (err)
- {
- /* We have been canceled ourselves. Give up. */
- cap_class->state = _HURD_CAP_STATE_GREEN;
- pthread_mutex_unlock (&cap_class->lock);
- return err;
- }
- }
- while (cap_class->state != _HURD_CAP_STATE_RED);
- }
- else
- cap_class->state = _HURD_CAP_STATE_RED;
-
- /* Now all pending RPCs have been canceled and are completed (except
- us), and all incoming RPCs are inhibited. */
- pthread_mutex_unlock (&cap_class->lock);
-
- return 0;
-}
-
-
-/* Resume RPCs on the class CAP_CLASS and wake-up all waiters. */
-void
-hurd_cap_class_resume (hurd_cap_class_t cap_class)
-{
- pthread_mutex_lock (&cap_class->lock);
-
- cap_class->state = _HURD_CAP_STATE_GREEN;
-
- /* Broadcast the change to all potential waiters. */
- pthread_cond_broadcast (&cap_class->cond);
-
- pthread_mutex_unlock (&cap_class->lock);
-}
diff --git a/libhurd-cap-server/class-init.c b/libhurd-cap-server/class-init.c
deleted file mode 100644
index 150fa96..0000000
--- a/libhurd-cap-server/class-init.c
+++ /dev/null
@@ -1,180 +0,0 @@
-/* class-init.c - Initialize a capability class.
- Copyright (C) 2004, 2005 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. */
-
-#if HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <errno.h>
-#include <assert.h>
-#include <stdlib.h>
-#include <pthread.h>
-
-#include <hurd/slab.h>
-#include <hurd/cap-server.h>
-
-
-/* Initialize the slab object pointed to by BUFFER. HOOK is as
- provided to hurd_slab_create. */
-static error_t
-_hurd_cap_obj_constructor (void *hook, void *buffer)
-{
- hurd_cap_class_t cap_class = (hurd_cap_class_t) hook;
- hurd_cap_obj_t obj = (hurd_cap_obj_t) buffer;
- error_t err;
-
- /* First do our own initialization. */
- obj->cap_class = cap_class;
-
- err = pthread_mutex_init (&obj->lock, 0);
- if (err)
- return err;
-
- obj->refs = 1;
- obj->state = _HURD_CAP_STATE_GREEN;
- obj->pending_rpcs = NULL;
- /* The member COND_WAITER does not need to be initialized. */
- obj->clients = NULL;
-
- /* Then do the user part, if necessary. */
- if (cap_class->obj_init)
- {
- err = (*cap_class->obj_init) (cap_class, obj);
- if (err)
- {
- pthread_mutex_destroy (&obj->lock);
- return err;
- }
- }
-
- return 0;
-}
-
-
-/* Destroy the slab object pointed to by BUFFER. HOOK is as provided
- to hurd_slab_create. */
-static void
-_hurd_cap_obj_destructor (void *hook, void *buffer)
-{
- hurd_cap_class_t cap_class = (hurd_cap_class_t) hook;
- hurd_cap_obj_t obj = (hurd_cap_obj_t) buffer;
-
- if (cap_class->obj_destroy)
- (*cap_class->obj_destroy) (cap_class, obj);
-
- pthread_mutex_destroy (&obj->lock);
-}
-
-
-/* Same as hurd_cap_class_create, but doesn't allocate the storage for
- CAP_CLASS. Instead, you have to provide it. */
-error_t
-hurd_cap_class_init_untyped (hurd_cap_class_t cap_class,
- size_t size, size_t alignment,
- hurd_cap_obj_init_t obj_init,
- hurd_cap_obj_alloc_t obj_alloc,
- hurd_cap_obj_reinit_t obj_reinit,
- hurd_cap_obj_destroy_t obj_destroy,
- hurd_cap_class_demuxer_t demuxer)
-{
- error_t err;
-
- /* The alignment requirements must be a power of 2. */
- assert ((alignment & (alignment - 1)) == 0
- || ! "hurd_cap_class_init_untyped: "
- "requested alignment not a power of 2");
-
- /* Find the smallest alignment requirement common to the user object
- and a struct hurd_cap_obj. Since both are required to be a power
- of 2, we need simply take the larger one. */
- if (alignment < __alignof__(struct hurd_cap_obj))
- alignment = __alignof__(struct hurd_cap_obj);
-
- size += hurd_cap_obj_user_offset (alignment);
-
- /* Capability object management. */
-
- cap_class->obj_init = obj_init;
- cap_class->obj_alloc = obj_alloc;
- cap_class->obj_reinit = obj_reinit;
- cap_class->obj_destroy = obj_destroy;
-
- err = hurd_slab_init (&cap_class->obj_space, size, alignment, NULL, NULL,
- _hurd_cap_obj_constructor, _hurd_cap_obj_destructor,
- cap_class);
- if (err)
- goto err_obj_space;
-
- err = pthread_cond_init (&cap_class->obj_cond, NULL);
- if (err)
- goto err_obj_cond;
-
- err = pthread_mutex_init (&cap_class->obj_cond_lock, NULL);
- if (err)
- goto err_obj_cond_lock;
-
-
- /* Class management. */
-
- cap_class->demuxer = demuxer;
-
- err = pthread_mutex_init (&cap_class->lock, NULL);
- if (err)
- goto err_lock;
-
- cap_class->state = _HURD_CAP_STATE_GREEN;
-
- err = pthread_cond_init (&cap_class->cond, NULL);
- if (err)
- goto err_cond;
-
- /* The cond_waiter member doesn't need to be initialized. It is
- only valid when CAP_CLASS->STATE is _HURD_CAP_STATE_YELLOW. */
-
- cap_class->pending_rpcs = NULL;
-
- /* FIXME: Add the class to the list of classes to be served by
- RPCs. */
-
- return 0;
-
- /* This is provided here in case you add more initialization to the
- end of the above code. */
-#if 0
- pthread_cond_destroy (&cap_class->cond);
-#endif
-
- err_cond:
- pthread_mutex_destroy (&cap_class->lock);
-
- err_lock:
- pthread_mutex_destroy (&cap_class->obj_cond_lock);
-
- err_obj_cond_lock:
- pthread_cond_destroy (&cap_class->obj_cond);
-
- err_obj_cond:
- /* This can not fail at this point. */
- hurd_slab_destroy (&cap_class->obj_space);
-
- err_obj_space:
- return err;
-}
diff --git a/libhurd-cap-server/client-create.c b/libhurd-cap-server/client-create.c
deleted file mode 100644
index ac8c54a..0000000
--- a/libhurd-cap-server/client-create.c
+++ /dev/null
@@ -1,213 +0,0 @@
-/* client-create.c - Create a capability client.
- Copyright (C) 2004, 2005 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. */
-
-#if HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <errno.h>
-#include <assert.h>
-#include <pthread.h>
-#include <stdlib.h>
-
-#include "cap-server-intern.h"
-
-
-/* Client management code. */
-
-/* Allocate a new capability client structure for the slab cache. */
-static error_t
-_hurd_cap_client_constructor (void *hook, void *buffer)
-{
- _hurd_cap_client_t client = (_hurd_cap_client_t) buffer;
- error_t err;
-
- err = pthread_mutex_init (&client->lock, NULL);
- if (err)
- return err;
-
- client->state = _HURD_CAP_STATE_GREEN;
- client->pending_rpcs = NULL;
-
- /* Capabilities are mapped to clients many to many, so we can not
- use a location pointer. However, this is not critical as
- removing an entry only blocks out RPCs for the same client, and
- not others. */
- hurd_ihash_init (&client->caps_reverse, HURD_IHASH_NO_LOCP);
-
- return 0;
-
- /* This is provided here in case you add more initialization to the
- end of the above code. */
-#if 0
- pthread_mutex_destroy (&client->lock);
-
- return err;
-#endif
-}
-
-
-/* Allocate a new capability client structure for the slab cache. */
-static void
-_hurd_cap_client_destructor (void *hook, void *buffer)
-{
- _hurd_cap_client_t client = (_hurd_cap_client_t) buffer;
-
- hurd_ihash_destroy (&client->caps_reverse);
- hurd_table_destroy (&client->caps);
- pthread_mutex_destroy (&client->lock);
-}
-
-
-/* The global slab for all capability clients. */
-struct hurd_slab_space _hurd_cap_client_space
- = HURD_SLAB_SPACE_INITIALIZER (struct _hurd_cap_client, NULL, NULL,
- _hurd_cap_client_constructor,
- _hurd_cap_client_destructor, NULL);
-
-
-static error_t
-_hurd_cap_client_alloc (hurd_task_id_t task_id,
- _hurd_cap_client_t *r_client)
-{
- error_t err;
- void *new_client;
- _hurd_cap_client_t client;
-
- err = hurd_slab_alloc (&_hurd_cap_client_space, &new_client);
- if (err)
- return err;
-
- client = new_client;
-
- /* CLIENT->id will be initialized by the caller when adding the
- client to the client table of the class. */
- client->task_id = task_id;
-
- err = hurd_table_init (&client->caps, sizeof (_hurd_cap_obj_entry_t));
- if (err)
- {
- free (client);
- return err;
- }
-
- /* FIXME: We need to acquire a task info capability here. The task
- death notifications have been suspended by the caller. */
-
- *r_client = client;
- return 0;
-}
-
-
-/* Look up the client with the task ID TASK in the bucket BUCKET, and
- return it in R_CLIENT, with one additional reference. If it is not
- found, create it. */
-error_t
-__attribute__((visibility("hidden")))
-_hurd_cap_client_create (hurd_cap_bucket_t bucket,
- hurd_task_id_t task_id,
- _hurd_cap_client_t *r_client)
-{
- error_t err = 0;
- _hurd_cap_client_t client;
-
- pthread_mutex_lock (&bucket->lock);
- client = (_hurd_cap_client_t) hurd_ihash_find (&bucket->clients_reverse,
- task_id);
- if (client)
- {
- if (client->dead)
- err = EINVAL; /* FIXME: A more appropriate code? */
- else
- {
- client->refs++;
- *r_client = client;
- }
- pthread_mutex_unlock (&bucket->lock);
- return err;
- }
- pthread_mutex_unlock (&bucket->lock);
-
- /* The client is not yet registered. Block out processing task
- death notifications, create a new client structure, and then
- enter it into the table before resuming task death
- notifications. */
- hurd_task_death_notify_suspend ();
- err = _hurd_cap_client_alloc (task_id, r_client);
- if (err)
- {
- hurd_task_death_notify_resume ();
- return err;
- }
-
- pthread_mutex_lock (&bucket->lock);
- /* Since we dropped the bucket lock during the allocation (which is
- potentially long) we need to check that somebody else didn't
- already allocate a client data structure. If so, we can just use
- that. Otherwise, we continue. */
- client = (_hurd_cap_client_t) hurd_ihash_find (&bucket->clients_reverse,
- task_id);
- if (client)
- {
- if (client->dead)
- {
- err = EINVAL; /* FIXME: A more appropriate code? */
- pthread_mutex_unlock (&bucket->lock);
- }
- else
- {
- /* Somebody else was indeed faster. Use the existing entry. */
- client->refs++;
- pthread_mutex_unlock (&bucket->lock);
- _hurd_cap_client_dealloc (bucket, *r_client);
- *r_client = client;
- }
- return err;
- }
-
- client = *r_client;
-
- /* One reference for the fact that the client task lives, one for
- the caller. */
- client->refs = 2;
-
- err = hurd_table_enter (&bucket->clients, &client, &client->id);
- if (!err)
- {
- err = hurd_ihash_add (&bucket->clients_reverse, task_id, client);
- if (err)
- hurd_table_remove (&bucket->clients, client->id);
- }
- if (err)
- {
- pthread_mutex_unlock (&bucket->lock);
- hurd_task_death_notify_resume ();
-
- _hurd_cap_client_dealloc (bucket, client);
- return err;
- }
- pthread_mutex_unlock (&bucket->lock);
- hurd_task_death_notify_resume ();
-
- *r_client = client;
-
- return 0;
-}
diff --git a/libhurd-cap-server/client-inhibit.c b/libhurd-cap-server/client-inhibit.c
deleted file mode 100644
index 2228b5f..0000000
--- a/libhurd-cap-server/client-inhibit.c
+++ /dev/null
@@ -1,157 +0,0 @@
-/* client-inhibit.c - Inhibit RPCs on a capability client.
- 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. */
-
-#if HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <errno.h>
-#include <pthread.h>
-#include <stdlib.h>
-
-#include "cap-server-intern.h"
-
-
-/* Inhibit all RPCs on the capability client CLIENT (which must not be
- locked) in the capability bucket BUCKET. You _must_ follow up
- with a hurd_cap_client_resume operation, and hold at least one
- reference to the object continuously until you did so. */
-error_t
-_hurd_cap_client_inhibit (hurd_cap_bucket_t bucket, _hurd_cap_client_t client)
-{
- error_t err;
-
- /* First take the bucket-wide lock for conditions on capability
- client states. */
- pthread_mutex_lock (&bucket->client_cond_lock);
-
- /* Then lock the client to check its state. */
- pthread_mutex_lock (&client->lock);
-
- /* First wait until any other inhibitor has resumed the capability
- client. This ensures that capability client inhibitions are
- fully serialized (per capability client). */
- while (client->state != _HURD_CAP_STATE_GREEN)
- {
- pthread_mutex_unlock (&client->lock);
- err = hurd_cond_wait (&bucket->client_cond,
- &bucket->client_cond_lock);
- if (err)
- {
- /* We have been canceled. */
- pthread_mutex_unlock (&bucket->client_cond_lock);
- return err;
- }
- pthread_mutex_lock (&client->lock);
- }
-
- /* Now it is our turn to inhibit the capability client. */
- client->cond_waiter = pthread_self ();
-
- if (_hurd_cap_client_cond_busy (client))
- {
- _hurd_cap_list_item_t pending_rpc = client->pending_rpcs;
-
- /* There are still pending RPCs (beside us). Cancel them. */
- while (pending_rpc)
- {
- if (pending_rpc->thread != client->cond_waiter)
- pthread_cancel (pending_rpc->thread);
- pending_rpc = pending_rpc->next;
- }
-
- /* Indicate that we would like to know when they have gone. */
- client->state = _HURD_CAP_STATE_YELLOW;
-
- /* The last one will shut the door. */
- do
- {
- pthread_mutex_unlock (&client->lock);
- err = hurd_cond_wait (&bucket->client_cond,
- &bucket->client_cond_lock);
- if (err)
- {
- /* We have been canceled ourselves. Give up. */
- client->state = _HURD_CAP_STATE_GREEN;
- pthread_mutex_unlock (&bucket->client_cond_lock);
- return err;
- }
- pthread_mutex_lock (&client->lock);
- }
- while (client->state != _HURD_CAP_STATE_RED);
- }
- else
- client->state = _HURD_CAP_STATE_RED;
-
- /* Now all pending RPCs have been canceled and are completed (except
- us), and all incoming RPCs are inhibited. */
- pthread_mutex_unlock (&client->lock);
- pthread_mutex_unlock (&bucket->client_cond_lock);
-
- return 0;
-}
-
-
-/* Resume RPCs on the capability client CLIENT in the bucket BUCKET
- and wake-up all waiters. */
-void
-_hurd_cap_client_resume (hurd_cap_bucket_t bucket, _hurd_cap_client_t client)
-{
- pthread_mutex_lock (&bucket->client_cond_lock);
- pthread_mutex_lock (&client->lock);
-
- client->state = _HURD_CAP_STATE_GREEN;
-
- /* Broadcast the change to all potential waiters. */
- pthread_cond_broadcast (&bucket->client_cond);
-
- pthread_mutex_unlock (&client->lock);
- pthread_mutex_unlock (&bucket->client_cond_lock);
-}
-
-
-/* End RPCs on the capability client CLIENT in the bucket BUCKET and
- wake-up all waiters. */
-void
-_hurd_cap_client_end (hurd_cap_bucket_t bucket, _hurd_cap_client_t client)
-{
- pthread_mutex_lock (&bucket->client_cond_lock);
- pthread_mutex_lock (&bucket->lock);
-
- client->state = _HURD_CAP_STATE_BLACK;
-
- /* Broadcast the change to all potential waiters. Even though the
- task is dead now, there is a race condition where we will process
- one spurious incoming RPC which is blocked on the inhibited
- state. So we wake up such threads, they will then go away
- quickly.
-
- Note that this does not work reliably for still living clients:
- They may bombard us with RPCs and thus keep the reference count
- of the client in the bucket table above 0 all the time, even in
- the _HURD_CAP_STATE_BLACK state. This is the reason that this
- interface is only for internal use (by
- _hurd_cap_client_death). */
- pthread_cond_broadcast (&bucket->client_cond);
-
- pthread_mutex_unlock (&bucket->lock);
- pthread_mutex_unlock (&bucket->client_cond_lock);
-}
diff --git a/libhurd-cap-server/client-release.c b/libhurd-cap-server/client-release.c
deleted file mode 100644
index 57d3796..0000000
--- a/libhurd-cap-server/client-release.c
+++ /dev/null
@@ -1,192 +0,0 @@
-/* client-release.c - Release a capability client.
- 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. */
-
-#if HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <errno.h>
-#include <pthread.h>
-#include <stdlib.h>
-
-#include <compiler.h>
-
-#include "cap-server-intern.h"
-
-
-/* Deallocate the connection client CLIENT. */
-void
-_hurd_cap_client_dealloc (hurd_cap_bucket_t bucket, _hurd_cap_client_t client)
-{
- unsigned int nr_caps = 0;
-
- /* This function is only invoked if the reference count for the
- client entry in the client table of the class drops to 0, and
- after the table entry was removed. Usually, the last reference
- is removed by the task death notification handler.
-
- At that point, there are no more pending RPCs for this client (if
- there were, there would be a reference for each of them). This
- also means that all capability IDs have at most one internal
- reference, the one for all external references. */
-
- /* Note that although the client has been removed from the clients
- table in the class, there are still back-references for each and
- every capability object in our capability table caps. These
- capability entries all count as references to ourself. They are
- used for example if a capability is revoked. It is important to
- realize that such a revocation can happen anytime as long as
- there are still valid capability objects in the caps table of the
- client.
-
- So, to correctly release those references, we have to look up
- each capability object properly, acquiring our own internal
- reference for it, then we have to unlock the client to lock the
- capability object, to finally revoke our own capability and
- release the capability object reference. Only then can we
- reacquire our own lock and go on to the next capability. While
- we do not hold our lock, more capabilities can be revoked by
- other concurrent operations. However, no new capabilities are
- added, so one pass through the table is enough. */
-
- pthread_mutex_lock (&client->lock);
-
- /* Release all capability objects held by this user. Because we
- have to honor the locking order, this takes a while. */
- HURD_TABLE_ITERATE (&client->caps, idx)
- {
- _hurd_cap_obj_entry_t entry;
-
- entry = *((_hurd_cap_obj_entry_t *)
- HURD_TABLE_LOOKUP (&client->caps, idx));
-
- /* If there were no external references, the last internal
- reference would have been released before we get here. */
- assert (entry->external_refs);
-
- nr_caps++;
-
- /* The number of internal references is either one or zero. If
- it is one, then the capability is not revoked yet, so we have
- to do it. If it is zero, then the capability is revoked
- (dead), and we only have to clear the table entry. */
- if (!entry->dead)
- {
- hurd_cap_obj_t cap_obj = entry->cap_obj;
-
- assert (entry->internal_refs == 1);
-
- /* Acquire an internal reference to prevent that our own
- reference to the capability object is removed by a
- concurrent revocation as soon as we unlock the client.
- After all, the existing internal reference belongs to the
- capability object, and not to us. */
- entry->internal_refs++;
- pthread_mutex_unlock (&client->lock);
-
- pthread_mutex_lock (&cap_obj->lock);
- /* Check if we should revoke it, or if somebody else did already. */
- if (!entry->dead)
- {
- int found;
-
- /* We should revoke it. */
- pthread_mutex_lock (&client->lock);
- found = hurd_ihash_remove (&client->caps_reverse,
- (hurd_ihash_key_t) cap_obj);
- assert (found);
- entry->dead = 1;
-
- assert (entry->internal_refs == 2);
- entry->internal_refs--;
- pthread_mutex_unlock (&client->lock);
-
- /* FIXME: Remove it from the capabilities client list. */
- }
- pthread_mutex_unlock (&cap_obj->lock);
-
- pthread_mutex_lock (&client->lock);
- /* Now we can drop the capability object below. */
- assert (entry->dead);
- assert (entry->internal_refs == 1);
- assert (entry->external_refs);
- }
- else
- {
- /* If the capability is dead, we can simply drop it below. */
- assert (entry->internal_refs == 0);
- entry->internal_refs = 1;
- }
-
- entry->dead = 0;
- /* ENTRY->internal_refs is 1. */
- entry->external_refs = 1;
-
- /* Remove the entry. */
- hurd_slab_dealloc (&_hurd_cap_obj_entry_space, entry);
- hurd_table_remove (&client->caps, idx);
- }
-
- /* After all this ugly work, the rest is trivial. */
- if (client->state != _HURD_CAP_STATE_GREEN)
- client->state = _HURD_CAP_STATE_GREEN;
-
- assert (client->pending_rpcs == NULL);
-
- /* FIXME: Release the task info capability here. */
-
- /* FIXME: It would be a good idea to shrink the empty table and
- empty hash here, to reclaim resources and be able to eventually
- enforce a per-client quota. */
- pthread_mutex_unlock (&client->lock);
-
- pthread_mutex_lock (&bucket->lock);
- bucket->nr_caps -= nr_caps;
- pthread_mutex_unlock (&bucket->lock);
-
- hurd_slab_dealloc (&_hurd_cap_client_space, client);
-}
-
-
-/* Release a reference for the client with the ID IDX in bucket
- BUCKET. */
-void
-_hurd_cap_client_release (hurd_cap_bucket_t bucket, _hurd_cap_client_id_t idx)
-{
- _hurd_cap_client_t client;
-
- pthread_mutex_lock (&bucket->lock);
- client = *(_hurd_cap_client_t *) HURD_TABLE_LOOKUP (&bucket->clients, idx);
-
- if (EXPECT_TRUE (client->refs > 1))
- {
- client->refs--;
- pthread_mutex_unlock (&bucket->lock);
- }
- else
- {
- hurd_table_remove (&bucket->clients, idx);
- hurd_ihash_locp_remove (&bucket->clients_reverse, client->locp);
-
- pthread_mutex_unlock (&bucket->lock);
- _hurd_cap_client_dealloc (bucket, client);
- }
-}
diff --git a/libhurd-cap-server/ctx-cap-use.c b/libhurd-cap-server/ctx-cap-use.c
deleted file mode 100644
index 3758c19..0000000
--- a/libhurd-cap-server/ctx-cap-use.c
+++ /dev/null
@@ -1,278 +0,0 @@
-/* ctx-cap-use.c - Use capabilities within an RPC context.
- Copyright (C) 2005 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. */
-
-#if HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <errno.h>
-#include <stdlib.h>
-
-#include <hurd/cap-server.h>
-
-#include <compiler.h>
-
-#include "cap-server-intern.h"
-
-
-/* Return the number of bytes required for a hurd_cap_ctx_cap_use
- structure. */
-size_t
-hurd_cap_ctx_size (void)
-{
- return sizeof (struct hurd_cap_ctx_cap_use);
-}
-
-/* If you want to use other capabilities in an RPC handler beside the
- one on which the RPC was invoked, you need to make sure that
- inhibition works on those other capabilities and cancel your
- operation. For this, the following interfaces are provided. */
-
-/* The calling thread wishes to execute an RPC on the the handle
- HANDLE. The calling thread must already be registered as executing
- an RPC. RPC_CTX is the cooresponding RPC context. The function
- uses the structure CAP_USE, which must point to the number of bytes
- returned by hurd_cap_ctx_size, to store data required by
- hurd_cap_ctx_end_cap_use. The capability object corresponding to
- HANDLE is locked and returned in *OBJP.
-
- Returns EINVAL if the capability handle is invalid for the client.
-
- Returns ENOENT if there is no object associated with handle HANDLE.
-
- Returns EBAD if the capability is dead.
-
- Returns EDOM if the object associated with HANDLE is not in class
- REQUIRED_CLASS. If no type check is required, it will be skipped
- if REQURIED_CLASS is NULL. */
-error_t
-hurd_cap_ctx_start_cap_use (hurd_cap_rpc_context_t rpc_ctx,
- hurd_cap_handle_t handle,
- hurd_cap_class_t required_class,
- struct hurd_cap_ctx_cap_use *cap_use,
- hurd_cap_obj_t *objp)
-{
- error_t err = 0;
- hurd_cap_bucket_t bucket = rpc_ctx->bucket;
- _hurd_cap_client_t client = rpc_ctx->client;
- hurd_cap_obj_t obj;
- hurd_cap_class_t cap_class;
- _hurd_cap_obj_entry_t obj_entry;
- _hurd_cap_obj_entry_t *obj_entryp;
-
-
- /* HANDLE must belong to the same client as RPC_CTX->HANDLE. */
- if (_hurd_cap_client_id (handle) != _hurd_cap_client_id (rpc_ctx->handle))
- return EINVAL;
-
- pthread_mutex_lock (&client->lock);
-
- /* Look up the object. */
- obj_entryp = (_hurd_cap_obj_entry_t *)
- hurd_table_lookup (&client->caps, _hurd_cap_id (handle));
- if (!obj_entryp)
- err = ENOENT;
- else
- {
- cap_use->_obj_entry = obj_entry = *obj_entryp;
-
- if (EXPECT_FALSE (!obj_entry->external_refs))
- err = ENOENT;
- else if (EXPECT_FALSE (obj_entry->dead))
- err = EBADF;
- else
- {
- obj_entry->internal_refs++;
- *objp = obj = obj_entry->cap_obj;
- }
- }
- pthread_mutex_unlock (&client->lock);
-
- if (err)
- /* Either the capability ID is invalid, or it was revoked. */
- return err;
-
- /* If HANDLE and RPC_CTX->HANDLE are the same, we are done. */
- if (EXPECT_FALSE (_hurd_cap_id (handle) == _hurd_cap_id (rpc_ctx->handle)))
- {
- assert (obj == rpc_ctx->obj);
- return 0;
- }
-
- /* At this point, CAP and OBJ are valid and we have one internal
- reference to the capability entry. */
-
- cap_class = obj->cap_class;
-
- if (required_class && cap_class != required_class)
- {
- err = EINVAL;
- goto client_cleanup;
- }
-
- if (cap_class != rpc_ctx->obj->cap_class)
- /* The capability class is not the same as the first caps. We
- need to add ourself to the cap class pending rpc list. */
- {
- pthread_mutex_lock (&cap_class->lock);
- /* First, we have to check if the class is inhibited, and if it is,
- we have to wait until it is uninhibited. */
- while (!err && cap_class->state != _HURD_CAP_STATE_GREEN)
- err = hurd_cond_wait (&cap_class->cond, &cap_class->lock);
- if (err)
- {
- /* Canceled. */
- pthread_mutex_unlock (&cap_class->lock);
- goto client_cleanup;
- }
-
- /* Now add ourself to the pending rpc list of the class */
- cap_use->_worker_class.thread = pthread_self ();
- cap_use->_worker_class.tid = l4_myself ();
- _hurd_cap_list_item_add (&cap_class->pending_rpcs,
- &cap_use->_worker_class);
-
- pthread_mutex_unlock (&cap_class->lock);
- }
-
- pthread_mutex_lock (&obj->lock);
- /* First, we have to check if the object is inhibited, and if it is,
- we have to wait until it is uninhibited. */
- if (obj->state != _HURD_CAP_STATE_GREEN)
- {
- pthread_mutex_unlock (&obj->lock);
- pthread_mutex_lock (&cap_class->obj_cond_lock);
- pthread_mutex_lock (&obj->lock);
- while (!err && obj->state != _HURD_CAP_STATE_GREEN)
- {
- pthread_mutex_unlock (&obj->lock);
- err = hurd_cond_wait (&cap_class->obj_cond,
- &cap_class->obj_cond_lock);
- pthread_mutex_lock (&obj->lock);
- }
- pthread_mutex_unlock (&cap_class->obj_cond_lock);
- }
- if (err)
- {
- /* Canceled. */
- pthread_mutex_unlock (&obj->lock);
- goto class_cleanup;
- }
-
- /* Now check if the client still has the capability, or if it was
- revoked. */
- pthread_mutex_lock (&client->lock);
- if (obj_entry->dead)
- err = EBADF;
- pthread_mutex_unlock (&client->lock);
- if (err)
- {
- /* The capability was revoked in the meantime. */
- pthread_mutex_unlock (&obj->lock);
- goto class_cleanup;
- }
-
- cap_use->_worker_obj.thread = pthread_self ();
- cap_use->_worker_obj.tid = l4_myself ();
- _hurd_cap_list_item_add (&cap_class->pending_rpcs, &cap_use->_worker_obj);
-
- /* At this point, we have looked up the capability, acquired an
- internal reference for its entry in the client table (which
- implicitely keeps a reference acquired for the object itself),
- acquired a reference for the capability client in the bucket, and
- have added an item to the pending_rpcs lists in the class (if
- necessary) and object. The object is locked. */
-
- return 0;
-
- class_cleanup:
- if (cap_use->_obj_entry->cap_obj->cap_class != rpc_ctx->obj->cap_class)
- /* Different classes. */
- {
- pthread_mutex_lock (&cap_class->lock);
- _hurd_cap_list_item_remove (&cap_use->_worker_class);
- _hurd_cap_class_cond_check (cap_class);
- pthread_mutex_unlock (&cap_class->lock);
- }
-
- client_cleanup:
- pthread_mutex_lock (&client->lock);
-
- /* You are not allowed to revoke a capability while there are
- pending RPCs on it. This is the reason we know that there must
- be at least one extra internal reference. FIXME: For
- cleanliness, this could still call some inline function that does
- the decrement. The assert can be a hint to the compiler to
- optimize the inline function expansion anyway. */
- assert (!obj_entry->dead);
- assert (obj_entry->internal_refs > 1);
- obj_entry->internal_refs--;
- pthread_mutex_unlock (&client->lock);
-
- return err;
-}
-
-
-/* End the use of the object CAP_USE->OBJ, which must be locked. */
-void
-hurd_cap_ctx_end_cap_use (hurd_cap_rpc_context_t rpc_ctx,
- struct hurd_cap_ctx_cap_use *cap_use)
-{
- _hurd_cap_obj_entry_t entry = cap_use->_obj_entry;
- hurd_cap_obj_t obj = entry->cap_obj;
- _hurd_cap_client_t client = rpc_ctx->client;
-
- /* Is this an additional use of the main capability object? */
- if (EXPECT_TRUE (obj != rpc_ctx->obj))
- /* No. */
- {
- hurd_cap_class_t cap_class = obj->cap_class;
-
- /* End the RPC on the object. */
- _hurd_cap_list_item_remove (&cap_use->_worker_obj);
- _hurd_cap_obj_cond_check (obj);
-
- if (cap_class != rpc_ctx->obj->cap_class)
- /* The capability object is in a different class from the primary
- capability object. */
- {
- pthread_mutex_lock (&cap_class->lock);
- _hurd_cap_list_item_remove (&cap_use->_worker_class);
- _hurd_cap_class_cond_check (cap_class);
- pthread_mutex_unlock (&cap_class->lock);
- }
- }
-
- hurd_cap_obj_unlock (obj);
-
- /* You are not allowed to revoke a capability while there are
- pending RPCs on it. This is the reason why we know that there
- must be at least one extra internal reference. FIXME: For
- cleanliness, this could still call some inline function that does
- the decrement. The assert can be a hint to the compiler to
- optimize the inline function expansion anyway. */
-
- pthread_mutex_lock (&client->lock);
- assert (!entry->dead);
- assert (entry->internal_refs > 1);
- entry->internal_refs--;
- pthread_mutex_unlock (&client->lock);
-}
diff --git a/libhurd-cap-server/headers.m4 b/libhurd-cap-server/headers.m4
deleted file mode 100644
index 886469e..0000000
--- a/libhurd-cap-server/headers.m4
+++ /dev/null
@@ -1,13 +0,0 @@
-# headers.m4 - Autoconf snippets to install links for header files.
-# Copyright 2003 Free Software Foundation, Inc.
-# Written by Marcus Brinkmann <marcus@gnu.org>.
-#
-# This file is free software; as a special exception the author gives
-# unlimited permission to copy and/or distribute it, with or without
-# modifications, as long as this notice is preserved.
-#
-# This file is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY, to the extent permitted by law; without even the
-# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-
-AC_CONFIG_LINKS([include/hurd/cap-server.h:libhurd-cap-server/cap-server.h])
diff --git a/libhurd-cap-server/obj-copy-out.c b/libhurd-cap-server/obj-copy-out.c
deleted file mode 100644
index c0e8b93..0000000
--- a/libhurd-cap-server/obj-copy-out.c
+++ /dev/null
@@ -1,121 +0,0 @@
-/* obj-copy-out.c - Copy out a capability to a client.
- 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. */
-
-#if HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <errno.h>
-#include <pthread.h>
-#include <stdlib.h>
-
-#include "cap-server-intern.h"
-
-
-/* Copy out a capability for the capability OBJ to the user CLIENT.
- Returns the capability ID (valid only for this user) in *R_ID, or
- an error. OBJ must be locked. Note: No internal reference for
- this capability is allocated for the caller. */
-error_t
-_hurd_cap_obj_copy_out (hurd_cap_obj_t obj, hurd_cap_bucket_t bucket,
- _hurd_cap_client_t client, _hurd_cap_id_t *r_id)
-{
- void *new_entry;
- _hurd_cap_obj_entry_t entry;
-
- pthread_mutex_lock (&client->lock);
- entry = (_hurd_cap_obj_entry_t) hurd_ihash_find (&client->caps_reverse,
- (hurd_ihash_key_t) obj);
-
- if (entry)
- {
- entry->external_refs++;
- *r_id = entry->id;
- pthread_mutex_unlock (&client->lock);
- return 0;
- }
- else
- {
- _hurd_cap_obj_entry_t entry_check;
- error_t err;
-
- pthread_mutex_unlock (&client->lock);
- err = hurd_slab_alloc (&_hurd_cap_obj_entry_space, &new_entry);
- if (err)
- return err;
- entry = new_entry;
-
- entry->cap_obj = obj;
- /* ID is filled in when adding the object to the table. */
- /* CLIENT_ITEM is filled after the object has been entered. */
- /* DEAD is 0 for initialized objects. */
- /* INTERNAL_REFS is 1 for initialized objects. */
- /* EXTERNAL_REFS is 1 for initialized objects. */
-
- pthread_mutex_lock (&client->lock);
- entry_check = hurd_ihash_find (&client->caps_reverse,
- (hurd_ihash_key_t) obj);
- if (entry_check)
- {
- /* Somebody else was faster. */
- entry_check->external_refs++;
- *r_id = entry_check->id;
- pthread_mutex_unlock (&client->lock);
- hurd_slab_dealloc (&_hurd_cap_obj_entry_space, entry);
- return 0;
- }
-
- /* Add the entry to the cap table of the client. */
- err = hurd_table_enter (&client->caps, &entry, &entry->id);
- if (err)
- {
- pthread_mutex_unlock (&client->lock);
- hurd_slab_dealloc (&_hurd_cap_obj_entry_space, entry);
- return err;
- }
- err = hurd_ihash_add (&client->caps_reverse,
- (hurd_ihash_key_t) obj, entry);
- if (err)
- {
- hurd_table_remove (&client->caps, entry->id);
- pthread_mutex_unlock (&client->lock);
- hurd_slab_dealloc (&_hurd_cap_obj_entry_space, entry);
- return err;
- }
-
- *r_id = entry->id;
- pthread_mutex_unlock (&client->lock);
-
- /* Add the object to the list. */
- _hurd_cap_list_item_add (&obj->clients, &entry->client_item);
-
- /* Add a reference for the internal reference of the capability
- entry to the capability object. */
- obj->refs++;
-
- /* FIXME: Should probably use spin lock here, or so. */
- pthread_mutex_lock (&bucket->lock);
- bucket->nr_caps++;
- pthread_mutex_unlock (&bucket->lock);
-
- return 0;
- }
-}
diff --git a/libhurd-cap-server/obj-dealloc.c b/libhurd-cap-server/obj-dealloc.c
deleted file mode 100644
index de4421e..0000000
--- a/libhurd-cap-server/obj-dealloc.c
+++ /dev/null
@@ -1,50 +0,0 @@
-/* obj-dealloc.c - Deallocate a capability object.
- 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. */
-
-#if HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <assert.h>
-#include <pthread.h>
-
-#include "cap-server-intern.h"
-
-
-/* Deallocate the capability object OBJ, which must be locked and have
- no more references. */
-void
-_hurd_cap_obj_dealloc (hurd_cap_obj_t obj)
-{
- hurd_cap_class_t cap_class = obj->cap_class;
-
- /* First let the user do their reinitialization. */
- (*cap_class->obj_reinit) (cap_class, obj);
-
- /* Now do our part of the reinitialization. */
- assert (obj->refs == 0);
- assert (obj->state == _HURD_CAP_STATE_GREEN);
- assert (obj->pending_rpcs == NULL);
- assert (obj->clients == NULL);
- hurd_cap_obj_unlock (obj);
-
- hurd_slab_dealloc (&cap_class->obj_space, obj);
-}
diff --git a/libhurd-cap-server/obj-drop.c b/libhurd-cap-server/obj-drop.c
deleted file mode 100644
index 6942ab1..0000000
--- a/libhurd-cap-server/obj-drop.c
+++ /dev/null
@@ -1,36 +0,0 @@
-/* obj-drop.c - Drop a reference to a capability object.
- 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. */
-
-#if HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include "cap-server-intern.h"
-
-
-/* Remove one reference for the capability object OBJ, which must be
- locked, and will be unlocked when the function returns. If this
- was the last user of this object, the object is deallocated. */
-void
-hurd_cap_obj_drop (hurd_cap_obj_t obj)
-{
- _hurd_cap_obj_drop (obj);
-}
diff --git a/libhurd-cap-server/obj-entry-space.c b/libhurd-cap-server/obj-entry-space.c
deleted file mode 100644
index 5eb33ba..0000000
--- a/libhurd-cap-server/obj-entry-space.c
+++ /dev/null
@@ -1,52 +0,0 @@
-/* obj-entry-space.c - The capability object entry slab space.
- Copyright (C) 2004, 2005 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. */
-
-#if HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <errno.h>
-
-#include <hurd/slab.h>
-
-#include "cap-server-intern.h"
-
-
-static error_t
-_hurd_cap_obj_entry_constructor (void *hook, void *buffer)
-{
- _hurd_cap_obj_entry_t entry = (_hurd_cap_obj_entry_t) buffer;
-
- /* The members cap_obj and client_item are initialized at
- instantiation time. */
-
- entry->dead = 0;
- entry->internal_refs = 1;
- entry->external_refs = 1;
-
- return 0;
-}
-
-
-/* The global slab for all capability entries. */
-struct hurd_slab_space _hurd_cap_obj_entry_space
- = HURD_SLAB_SPACE_INITIALIZER (struct _hurd_cap_obj_entry, NULL, NULL,
- _hurd_cap_obj_entry_constructor, NULL, NULL);
diff --git a/libhurd-cap-server/obj-inhibit.c b/libhurd-cap-server/obj-inhibit.c
deleted file mode 100644
index 22455b3..0000000
--- a/libhurd-cap-server/obj-inhibit.c
+++ /dev/null
@@ -1,131 +0,0 @@
-/* obj-inhibit.c - Inhibit RPCs on a capability object.
- 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. */
-
-#if HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <errno.h>
-#include <pthread.h>
-#include <stdlib.h>
-
-#include "cap-server-intern.h"
-
-
-/* Inhibit all RPCs on the capability object CAP_OBJ (which must not
- be locked). You _must_ follow up with a hurd_cap_obj_resume
- operation, and hold at least one reference to the object
- continuously until you did so. */
-error_t
-hurd_cap_obj_inhibit (hurd_cap_obj_t obj)
-{
- hurd_cap_class_t cap_class = obj->cap_class;
- error_t err;
-
- /* First take the class-wide lock for conditions on capability
- object states. */
- pthread_mutex_lock (&cap_class->obj_cond_lock);
-
- /* Then lock the object to check its state. */
- pthread_mutex_lock (&obj->lock);
-
- /* First wait until any other inhibitor has resumed the capability
- object. This ensures that capability object inhibitions are
- fully serialized (per capability object). */
- while (obj->state != _HURD_CAP_STATE_GREEN)
- {
- pthread_mutex_unlock (&obj->lock);
- err = hurd_cond_wait (&cap_class->obj_cond,
- &cap_class->obj_cond_lock);
- if (err)
- {
- /* We have been canceled. */
- pthread_mutex_unlock (&cap_class->obj_cond_lock);
- return err;
- }
- pthread_mutex_lock (&obj->lock);
- }
-
- /* Now it is our turn to inhibit the capability object. */
- obj->cond_waiter = pthread_self ();
-
- if (_hurd_cap_obj_cond_busy (obj))
- {
- _hurd_cap_list_item_t pending_rpc = obj->pending_rpcs;
-
- /* There are still pending RPCs (beside us). Cancel them. */
- while (pending_rpc)
- {
- if (pending_rpc->thread != obj->cond_waiter)
- pthread_cancel (pending_rpc->thread);
- pending_rpc = pending_rpc->next;
- }
-
- /* Indicate that we would like to know when they have gone. */
- obj->state = _HURD_CAP_STATE_YELLOW;
-
- /* The last one will shut the door. */
- do
- {
- pthread_mutex_unlock (&obj->lock);
- err = hurd_cond_wait (&cap_class->obj_cond,
- &cap_class->obj_cond_lock);
- if (err)
- {
- /* We have been canceled ourselves. Give up. */
- obj->state = _HURD_CAP_STATE_GREEN;
- pthread_mutex_unlock (&cap_class->obj_cond_lock);
- return err;
- }
- pthread_mutex_lock (&obj->lock);
- }
- while (obj->state != _HURD_CAP_STATE_RED);
- }
- else
- obj->state = _HURD_CAP_STATE_RED;
-
- /* Now all pending RPCs have been canceled and are completed (except
- us), and all incoming RPCs are inhibited. */
- pthread_mutex_unlock (&obj->lock);
- pthread_mutex_unlock (&cap_class->obj_cond_lock);
-
- return 0;
-}
-
-
-/* Resume RPCs on the capability object OBJ and wake-up all
- waiters. */
-void
-hurd_cap_obj_resume (hurd_cap_obj_t obj)
-{
- hurd_cap_class_t cap_class = obj->cap_class;
-
- pthread_mutex_lock (&cap_class->obj_cond_lock);
- pthread_mutex_lock (&obj->lock);
-
- obj->state = _HURD_CAP_STATE_GREEN;
-
- /* Broadcast the change to all potential waiters. */
- pthread_cond_broadcast (&cap_class->obj_cond);
-
- pthread_mutex_unlock (&obj->lock);
- pthread_mutex_unlock (&cap_class->obj_cond_lock);
-}
diff --git a/libhurd-cap-server/table.c b/libhurd-cap-server/table.c
deleted file mode 100644
index 8a0acd3..0000000
--- a/libhurd-cap-server/table.c
+++ /dev/null
@@ -1,96 +0,0 @@
-/* table.c - Table abstraction implementation.
- 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. */
-
-#if HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <assert.h>
-#include <string.h>
-
-#include "table.h"
-
-
-/* Initialize the table TABLE. */
-error_t
-hurd_table_init (hurd_table_t table, unsigned int entry_size)
-{
- assert (sizeof (entry_size) >= sizeof (void *));
-
- *table = (struct hurd_table) HURD_TABLE_INITIALIZER (entry_size);
- return 0;
-}
-
-
-/* Destroy the table TABLE. */
-void
-hurd_table_destroy (hurd_table_t table)
-{
- if (table->data)
- free (table->data);
-}
-
-
-/* The initial table size. */
-#define TABLE_START_SIZE 4
-
-/* Add the table element DATA to the table TABLE. The index for this
- element is returned in R_IDX. Note that the data is added by
- copying ENTRY_SIZE bytes into the table (the ENTRY_SIZE parameter
- was provided at table initialization time). */
-error_t
-hurd_table_enter (hurd_table_t table, void *data, unsigned int *r_idx)
-{
- unsigned int idx;
-
- if (table->used == table->size)
- {
- unsigned int size_new = table->size ? 2 * table->size : TABLE_START_SIZE;
- void *data_new;
-
- data_new = realloc (table->data, size_new * table->entry_size);
- if (!data_new)
- return errno;
-
- table->first_free = table->size;
- table->data = data_new;
- table->size = size_new;
- }
-
- for (idx = table->first_free; idx < table->init_size; idx++)
- if (_HURD_TABLE_ENTRY_LOOKUP (table, idx) == HURD_TABLE_EMPTY)
- break;
-
- /* The following setting for FIRST_FREE is safe, because if this was
- the last table entry, then the table is full and we will grow the
- table the next time we are called (if no elements are removed in
- the meantime. */
- table->first_free = idx + 1;
-
- if (idx == table->init_size)
- table->init_size++;
-
- memcpy (HURD_TABLE_LOOKUP (table, idx), data, table->entry_size);
- table->used++;
- *r_idx = idx;
- return 0;
-}
-
diff --git a/libhurd-cap-server/table.h b/libhurd-cap-server/table.h
deleted file mode 100644
index 4278466..0000000
--- a/libhurd-cap-server/table.h
+++ /dev/null
@@ -1,207 +0,0 @@
-/* table.h - Table abstraction 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_TABLE_H
-#define _HURD_TABLE_H 1
-
-#include <errno.h>
-#include <stdlib.h>
-#include <assert.h>
-
-
-/* The hurd_table data type is a fancy array. At initialization time,
- you have to provide the size ENTRY_SIZE of each table entry. When
- you enter an element, you get an index number in return. This
- index can be used for fast lookup of table elements. You access
- the table elements through pointers to the beginning of the each
- block of ENTRY_SIZE bytes.
-
- Embedded at the beginning of the ENTRY_SIZE bytes in each slot is a
- void pointer. You can use this void pointer freely for your own
- purpose with the following restriction: In a used table entry, it
- must never be NULL. NULL at the beginning of a table entry
- indicates an unused (free) table entry.
-
- The table will grow (and eventually shrink, not yet implemented)
- automatically. New elements are always allocated from the
- beginning of the table. This means that when a new element is
- added, the free slot with the lowest index is always used. This
- makes slot usage predictable and attempts to prevent fragmentation
- and sparse usage.
-
- Note that tables, unlike hashes, can not be reorganized, because
- the index is not stable under reorganization.
-
- Of all operations supported, only lookup is immediate. Entering
- new elements is usually fast, too, unless the first free slot is
- unknown and has to be searched for, or there are no more free slots
- and the table has to be enlarged.
-
- Iterating over the used elements of the table is always
- of the order of the table size.
-
- In the future, removing an element can also shrink the table. In
- order to be able to do this, the implementation keeps track of the
- last used slot. For this reason, the remove operation is sometimes
- not immediate. */
-
-
-/* Because the first element in each table entry is a pointer, the
- table entry should be naturally aligned. */
-#define _HURD_TABLE_ALIGN(x) \
- (((x) + sizeof (void *) - 1) & ~(sizeof (void *) - 1))
-
-
-/* The value used for empty table entries. */
-#define HURD_TABLE_EMPTY (NULL)
-
-struct hurd_table
-{
- /* The size of one entry. Must at least be sizeof (void *). At the
- beginning of each entry, a void * should be present that is
- HURD_TABLE_EMPTY for unused elements and something else for used
- table elements. */
- unsigned int entry_size;
-
- /* The number of allocated table entries. */
- unsigned int size;
-
- /* The number of table entries that are initialized. */
- unsigned int init_size;
-
- /* The number of used table entries. */
- unsigned int used;
-
- /* The index of the lowest entry that is unused. */
- unsigned int first_free;
-
- /* The index after the highest entry that is used. */
- unsigned int last_used;
-
- /* The table data. */
- char *data;
-};
-typedef struct hurd_table *hurd_table_t;
-
-
-#define HURD_TABLE_INITIALIZER(size_of_one) \
- { .entry_size = _HURD_TABLE_ALIGN (size_of_one), .size = 0, \
- .init_size = 0, .used = 0, .first_free = 0, .last_used = 0, \
- .data = NULL }
-
-/* Fast accessor without range check. */
-#define HURD_TABLE_LOOKUP(table, idx) \
- (&(table)->data[(idx) * (table)->entry_size])
-
-/* This is an lvalue for the pointer embedded in the table entry. */
-#define _HURD_TABLE_ENTRY(entry) (*(void **) (entry))
-
-#define _HURD_TABLE_ENTRY_LOOKUP(table, idx) \
- _HURD_TABLE_ENTRY (HURD_TABLE_LOOKUP (table, idx))
-
-
-/* Initialize the table TABLE. */
-error_t hurd_table_init (hurd_table_t table, unsigned int entry_size);
-
-
-/* Destroy the table TABLE. */
-void hurd_table_destroy (hurd_table_t table);
-
-
-/* Add the table element DATA to the table TABLE. The index for this
- element is returned in R_IDX. Note that the data is added by
- copying ENTRY_SIZE bytes into the table (the ENTRY_SIZE parameter
- was provided at table initialization time). */
-error_t hurd_table_enter (hurd_table_t table, void *data, unsigned int *r_idx);
-
-
-/* Lookup the table element with the index IDX in the table TABLE. If
- there is no element with this index, return NULL. Otherwise a
- pointer to the table entry is returned. */
-static inline void *
-hurd_table_lookup (hurd_table_t table, unsigned int idx)
-{
- void *result;
-
- if (idx >= table->init_size)
- return NULL;
-
- result = HURD_TABLE_LOOKUP (table, idx);
- if (_HURD_TABLE_ENTRY (result) == HURD_TABLE_EMPTY)
- return NULL;
-
- return result;
-}
-
-
-/* Remove the table element with the index IDX from the table
- TABLE. */
-static inline void
-hurd_table_remove (hurd_table_t table, unsigned int idx)
-{
- void *entry;
-
- assert (idx < table->init_size);
-
- entry = HURD_TABLE_LOOKUP (table, idx);
- assert (_HURD_TABLE_ENTRY (entry) != HURD_TABLE_EMPTY);
-
- _HURD_TABLE_ENTRY (entry) = HURD_TABLE_EMPTY;
-
- if (idx < table->first_free)
- table->first_free = idx;
-
- if (idx == table->last_used - 1)
- while (--table->last_used > 0)
- if (_HURD_TABLE_ENTRY_LOOKUP (table, table->last_used - 1)
- == HURD_TABLE_EMPTY)
- break;
-
- table->used--;
-}
-
-
-/* Iterate over all elements in the table. You use this macro
- with a block, for example like this:
-
- error_t err;
- HURD_TABLE_ITERATE (table, idx)
- {
- err = foo (idx);
- if (err)
- break;
- }
- if (err)
- cleanup_and_return ();
-
- Or even like this:
-
- HURD_TABLE_ITERATE (ht, idx)
- foo (idx);
-
- The block will be run for every used element in the table. Because
- IDX is already a verified valid table index, you can lookup the
- table entry with the fast macro HURD_TABLE_LOOKUP. */
-#define HURD_TABLE_ITERATE(table, idx) \
- for (unsigned int idx = 0; idx < (table)->init_size; idx++) \
- if (_HURD_TABLE_ENTRY_LOOKUP ((table), (idx)) != HURD_TABLE_EMPTY)
-
-#endif /* _HURD_TABLE_H */
diff --git a/libhurd-cap-server/task-death.c b/libhurd-cap-server/task-death.c
deleted file mode 100644
index 855ed7a..0000000
--- a/libhurd-cap-server/task-death.c
+++ /dev/null
@@ -1,77 +0,0 @@
-/* task-death.c - Task death notifications, implementation.
- 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. */
-
-#if HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <pthread.h>
-
-#include <hurd/types.h>
-#include "task-death.h"
-
-
-/* A lock that protects the linked list. It also is held when
- callback handlers are called. */
-pthread_mutex_t hurd_task_death_notify_lock = PTHREAD_MUTEX_INITIALIZER;
-
-/* The linked list of callback handlers. */
-struct hurd_task_death_notify_list_item *hurd_task_death_notify_list;
-
-
-static void *
-task_death_manager (void *unused)
-{
- /* FIXME. Needs to be implement when the task server supports
- it. Do the following:
-
- unsigned int nr_task_ids;
- unsigned int i;
- hurd_task_id_t task_ids[nr_task_ids];
-
- struct hurd_task_death_notify_list_item *item;
-
- pthread_mutex_lock (&hurd_task_death_notify_lock);
- item = hurd_task_death_notify_list;
- while (item)
- {
- for (i = 0; i < nr_task_ids; i++)
- (*item->notify_handler) (item->hook, task_id[i]);
- item = item->next;
- }
- pthread_mutex_unlock (&hurd_task_death_notify_lock);
-
- The only bit missing is the RPC loop to retrieve the dead task ids
- from the task server. This can be a tight loop. */
-
- return 0;
-}
-
-
-/* Start task death notifications. Must be called once at startup. */
-error_t
-hurd_task_death_notify_start (void)
-{
- /* FIXME. Needs to be implement when the task server supports it.
- Start the task_death_manager thread. */
-
- return 0;
-}
diff --git a/libhurd-cap-server/task-death.h b/libhurd-cap-server/task-death.h
deleted file mode 100644
index c4b72a8..0000000
--- a/libhurd-cap-server/task-death.h
+++ /dev/null
@@ -1,123 +0,0 @@
-/* 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 */