summaryrefslogtreecommitdiff
path: root/hurd/rpc.h
diff options
context:
space:
mode:
authorNeal H. Walfield <neal@gnu.org>2008-12-12 10:20:33 +0100
committerNeal H. Walfield <neal@gnu.org>2008-12-12 10:20:33 +0100
commit57487c9bf316f3ed262d17e4c10b284a263b8187 (patch)
tree95b3ef42f0f0d0a1be513f912855385cc9688ca8 /hurd/rpc.h
parentf67f59da6de65186c674afb8e7307d6b23f48b63 (diff)
New IPC system. Update code accordingly.
hurd/ 2008-12-11 Neal H. Walfield <neal@gnu.org> Adapt RPC interfaces according to changes in IPC semantics. * messenger.h: New file. * message.h: New file. * ipc.h: New file. * headers.m4: Link sysroot/include/hurd/message.h to hurd/message.h, sysroot/include/hurd/messenger.h to hurd/messenger.h, and sysroot/include/hurd/ipc.h to hurd/ipc.h. * cap.h: Include <hurd/addr.h> and <stdbool.h>. (enum cap_type): Define cap_messenger, cap_rmessenger and cap_type_count. (cap_type_string): Handle cap_messenger and cap_rmessenger. (cap_types_compatible): Likewise. (cap_type_weak_p): Likewise. (cap_type_weaken): Likewise. (cap_type_strengthen): Likewise. (oid_t): Replace L4 type with standard type. (CAP_VOID): Define. * rpc.h [! RPC_TARGET]: Don't error out if not defined. [RPC_TARGET_ARG_]: Don't define or undefine. [RPC_TARGET_]: Likewise. [RPC_TARGET_NEED_ARG]: Ignore. Don't include <l4/ipc.h> or <l4/space.h>. Include <hurd/message.h> and <hurd/ipc.h>. (reply_buffer) [RM_INTERN]: Declare. (messenger_message_load) [RM_INTERN]: Likewise. [! RM_INTERN] Include <hurd/message-buffer.h>. (cap_t): Define. (CPP_FOREACH): Define. (CPP_SAFE_DEREF): Likewise. (RPC_ARGUMENTS): Take additional argument prefix. Use it. Update users. (RPC_CHOP): Rename from this... (RPC_CHOP2): ... to this. Update users. (RPC_TYPE_SHIFT): New define. (RPCLOADARG): Rewrite according to new marshalling semantics. (RPCSTOREARG): Likewise. (RPC_SEND_MARSHAL): Likewise. (RPC_SEND_UNMARSHAL): Likewise. (RPC_REPLY_MARSHAL): Likewise. (RPC_REPLY_UNMARSHAL): Likewise. (RPC_RECEIVE_MARSHAL): New define. (RPC_MARSHAL_GEN_): Break this into... (RPC_SEND_MARSHAL_GEN_): ... this... (RPC_RECEIVE_MARSHAL_GEN_): ... this... (RPC_REPLY_MARSHAL_GEN_): ... and this. Update users. (RPC_MARSHAL_GEN_): Redefine in terms of the new macros. (RPC_SEND_): Rewrite according to new marshalling and IPC semantics. (RPC_SEND_NONBLOCKING_): Define. (RPC_): Rewrite according to new marshalling and IPC semantics. (RPC_REPLY_): Likewise. (RPC_SIMPLE_): Don't define. (RPC_SIMPLE): Don't define. (RPC): Take additional argument ret_cap_count. Update users. (rpc_error_reply_marshal): Rewrite according to new marshalling and IPC semantics. (rpc_error_reply): Likewise. * t-rpc.c (RPC_TARGET_NEED_ARG): Don't define. (RPC_TARGET): Define. (RPC_noargs): Set to a large interger. (RPC_caps): New define. (noargs): Update interface specification according to new IDL interface. Update users. (onein): Likewise. (oneout): Likewise. (onlyin): Likewise. (onlyout): Likewise. (mix): Likewise. (noargs): Likewise. (onein): Likewise. (oneout): Likewise. (onlyin): Likewise. (onlyout): Likewise. (mix): New interface. (RPC_TARGET): Don't undefine. (main): Update to use the new RPC marshalling interface. Write a test using the new `mix' interface. * activity.h (RPC_TARGET_NEED_ARG): Don't undefine. (RPC_TARGET): Don't define. (activity_policy): Update interface specification according to new IDL interface. Update users. (activity_info): Likewise. * cap.h: (RPC_TARGET_NEED_ARG): Don't undefine. (RPC_TARGET): Don't define. (RM_object_slot_copy_out): Don't define. (RM_object_slot_copy_in): Likewise. (RM_object_slot_read): Likewise. (RM_object_reply_on_destruction): Define. (cap_copy): Update interface specification according to new IDL interface. Update users. (cap_rubout): Likewise. (cap_read): Likewise. (object_discarded_clear): Likewise. (object_discard): Likewise. (object_status): Likewise. (object_name): Likewise. (object_reply_on_destruction): New interface replacing thread_wait_destroy. (object_slot_copy_out): Remove interface. (object_slot_copy_in): Likewise. (object_slot_read): Likewise. (RPC_TARGET): Don't undefine. * exceptions.h: Don't include <l4/thread.h>. Include <l4/space.h>. (RPC_STUB_PREFIX): Redefine to `activation'. (RPC_ID_PREFIX EXCEPTION): Redefine to `ACTIVATION'. (RPC_TARGET_NEED_ARG): Don't define. (RPC_TARGET_ARG_TYPE): Likewise. (RPC_TARGET): Likewise. (EXCEPTION_fault): Rename from this... (ACTIVATION_fault): ... to this. Update users. (exception_method_id_string): Rename from this... (activation_method_id_string): ... to this. (struct exception_info): Rename from this... (struct activation_fault_info): ... to this. Update users. (EXCEPTION_INFO_FMT): Rename from this... (ACTIVATION_FAULT_INFO_FMT): ... to this. Update users. (EXCEPTION_INFO_PRINTF): Rename from this... (ACTIVATION_FAULT_INFO_PRINTF): ... to this. Update users. (fault): Update interface specification according to new IDL interface. Update users. * folio.h (RPC_TARGET_NEED_ARG): Don't undefine. (RPC_TARGET): Don't define. (folio_alloc): Update interface specification according to new IDL interface. Update users. (folio_free): Likewise. (folio_object_alloc): Likewise. (folio_policy): Likewise. (RPC_TARGET): Don't undefine. * futex.h (RPC_TARGET_NEED_ARG): Don't undefine. (RPC_TARGET): Don't define. (futex): Update interface specification according to new IDL interface. Update users. (RPC_TARGET): Don't undefine. (futex_using): New function. (futex): Implement in terms of it. (futex_wait_using): New function. (futex_wait): Implement in terms of it. (futex_wake_using): New function. (futex_wake): Implement in terms of it. * thread.h (RM_thread_wait_object_destroyed): Don't define. (RM_thread_raise_exception): Rename from this... (RM_thread_activation_collect): ... to this. (RM_thread_id): Define. (RPC_TARGET_NEED_ARG): Don't undefine. (RPC_TARGET): Don't define. (struct hurd_thread_exregs_in): Remove fields aspace, activity, exception_page, aspace_out, activity_out and exception_page_out. (thread_exregs): Update interface specification according to new IDL interface. Add additional parameters exception_messenger and exception_messenger_out. Update users. (thread_wait_object_destroyed): Remove interface. (struct exception_buffer): Don't define. (thread_raise_exception): Remove interface. (thread_id): New interface. (thread_activation_collect): Likewise. (RPC_TARGET): Don't undefine. * RPC: Update. * exceptions.h (hurd_activation_handler_init_early): New declaration. (hurd_activation_handler_init): Likewise. (hurd_utcb): Likewise. (EXCEPTION_STACK_SIZE_LOG2): Don't define. (EXCEPTION_STACK_SIZE): Likewise. (hurd_activation_state_alloc): New declaration. (exception_page_cleanup): Rename from this... (hurd_activation_state_free): ... to this. Update users. (exception_handler_activated): Rename from this... (hurd_activation_handler_activated): ... to this. (exception_handler_normal): Rename from this... (hurd_activation_handler_normal): ... to this. Update users. Take additional parameter utcb. (exception_handler_entry): Rename from this... (hurd_activation_handler_entry): ... to this. (exception_handler_end): Rename from this... (hurd_activation_handler_end): ... to this. (hurd_activation_message_register): New declaration. (hurd_activation_message_unregister): Likewise. (hurd_activation_stack_dump): Likewise. * thread.h [! __have_vg_thread_id_t] (__have_vg_thread_id_t): Define. [! __have_vg_thread_id_t && USE_L4]: Include <l4.h>. [! __have_vg_thread_id_t && !USE_L4]: Include <stdint.h>. [! __have_vg_thread_id_t] (vg_thread_id_t): Define. [! __have_vg_thread_id_t] (vg_niltid): Define. [! __have_vg_thread_id_t] (VG_THREAD_ID_FMT): Define. [! __have_activation_frame] (__have_activation_frame): Define. [! __have_activation_frame && USE_L4]: Include <l4/ipc.h>. [! __have_activation_frame] (struct hurd_message_buffer): Declare. [! __have_activation_frame] (struct activation_frame): Define in this case. Add fields normal_mode_stack and canary. [! __have_activation_frame && i386] (struct activation_frame): Change regs to have 10 elements. Add fields eax, ecx, edx, eflags, eip, ebx, edi, esi, ebp and esp. [! __have_activation_frame && !USE_L4] (struct activation_frame): Remove fields saved_sender, saved_receiver, saved_timeout, saved_error_code, saved_flags, and saved_br0 in this case. [__need_vg_thread_id_t || __need_activation_frame] (__need_vg_thread_id_t): Undefine. [__need_vg_thread_id_t || __need_activation_frame] (__need_activation_frame): Likewise. [!__need_vg_thread_id_t && !__need_activation_frame]: Include the rest of the file in this case. Include <stdint.h>, <hurd/types.h>, <hurd/addr.h>, <hurd/addr-trans.h>, <hurd/cap.h>, <hurd/messenger.h> and <setjmp.h>. (hurd_activation_frame_longjmp): New declaration. (struct hurd_fault_catcher): New definition. (hurd_fault_catcher_register): New declaration. (hurd_fault_catcher_unregister): Likewise. (struct exception_page): Rename from this... (struct vg_utcb): ... to this. Update users. Remove field exception. Add fields protected_payload, messenger_id, inline_words, inline_caps, inline_word_count, inline_cap_count, inline_data, exception_buffer, extant_messages, catchers, alternate_stack, alternate_stack_inuse, canary0, canary1. (UTCB_CANARY0): Define. (UTCB_CANARY1): Likewise. (THREAD_EXCEPTION_PAGE_SLOT): Rename from this... (THREAD_UTCB): ... to this. (THREAD_EXCEPTION_MESSENGER): Define. (THREAD_SLOTS): Likewise. (THREAD_SLOTS_LOG2): Likewise. (HURD_EXREGS_SET_EXCEPTION_PAGE): Rename from this... (HURD_EXREGS_SET_UTCB): ... to this. Update users. (HURD_EXREGS_SET_EXCEPTION_MESSENGER): Define. (HURD_EXREGS_SET_REGS): Add HURD_EXREGS_SET_EXCEPTION_MESSENGER. (vg_myself): New function. * startup.h (struct hurd_startup_data): Add field messengers. viengoos/ 2008-12-12 Neal H. Walfield <neal@gnu.org> Implement messengers and convert to new IPC semantics. * messenger.h: New file. * messenger.c: New file. * Makefile.am (viengoos_SOURCES): Add messenger.h and messenger.c. * ager.c: Include "messenger.h". (update_stats): Update notifivation code to use messengers. * cap.c: Include <hurd/messenger.h>. (cap_shootdown): Follow thread and messenger objects. * object.h (object_wait_queue_head): Use and return struct messenger *'s, not struct thread *'s. Update users. (object_wait_queue_tail): Likewise. (object_wait_queue_next): Likewise. (object_wait_queue_prev): Likewise. (object_wait_queue_enqueue): Likewise. (object_wait_queue_dequeue): Likewise. Rename from this... (object_wait_queue_unlink): ... to this. (object_wait_queue_push): New declaration. (folio_object_wait_queue_for_each): Use and return struct messenger *'s, not struct thread *'s. Update users. (object_wait_queue_for_each): Likewise. * object.c: Include <hurd/messenger.h> and "messenger.h". (folio_object_alloc): When destroying a messenger, call messenger_destroy. (folio_object_alloc): Send notifications using messengers. (object_wait_queue_head): Use and return struct messenger *'s, not struct thread *'s. (object_wait_queue_tail): Likewise. (object_wait_queue_next): Likewise. (object_wait_queue_prev): Likewise. (object_wait_queue_check): Likewise. (object_wait_queue_enqueue): Likewise. Add MESSENGER to end of the queue, not the beginning. (object_wait_queue_push): New function. (object_wait_queue_dequeue): Use and return struct messenger *'s, not struct thread *'s. Rename from this... (object_wait_queue_unlink): ... to this. * pager.c: Include "messenger.h". * thread.h: Don't include "list.h". Include <hurd/cap.h> and <hurd/thread.h>. (struct folio): Remove declaration. (THREAD_SLOTS): Don't define. (THREAD_WAIT_FUTEX): Move from here... * messenger.h (MESSENGER_WAIT_FUTEX): ... to here. * thread.h (THREAD_WAIT_DESTROY): Move from here... * messenger.h (MESSENGER_WAIT_DESTROY): ... to here. * thread.h (THREAD_WAIT_ACTIVITY_INFO): Move from here... * messenger.h (MESSENGER_WAIT_ACTIVITY_INFO): ... to here. * thread.h (struct thread): Rename field exception_page to utcb. Add field exception_messenger. Remove fields wait_queue_p, wait_queue_head, wait_queue_tail, wait_reason, wait_reason_arg, wait_reason_arg2, wait_queue and futex_waiter_node. (futex_waiters): Don't declare. (thread_exregs): Change input capabilities to not be pointers to capabilities but just capability structures. Add argument exception_messenger. Remove arguments aspace_out, activity_out and exception_page_out. Update users. (thread_activate): New declaration. (thread_raise_exception): Change MSG's type to be struct vg_message *. Update users. (thread_deliver_pending): New declaration. * thread.c (thread_deinit): Remove code to remove THREAD from a wait queue. (thread_exregs): Change input capabilities to not be pointers to capabilities but just capability structures. Update code. Add argument exception_messenger. Set THREAD's exception messenger according to it and CONTROL. Remove arguments aspace_out, activity_out and exception_page_out. Don't save the old capabilities. (thread_raise_exception): Move body of function... (thread_activate): ... to this new function. Update to use messengers. (thread_raise_exception): Implement in terms of it. (thread_deliver_pending): New function. * server.c: Include <hurd/ipc.h> and "messenger.h". (DEBUG): If label is the IPC label, use "IPC" as the function. (OBJECT_): Take additional parameter WRITABLE. Save whether the object is writable in *WRITABLE. Update users. (OBJECT): Likewise. (server_loop): Update to use messengers and the new IPC interface. Update method implementations appropriately. Don't marshal faults using exception_fault_send_marshal but the new activation_fault_send_marshal. Remove implementations of object_slot_copy_out, object_slot_copy_in and object_slot_read. Reimplement object_discard. In the thread_exregs implementation, handle the exception messenger. Implement thread_id. Remove thread_wait_object_destroyed. Implement object_reply_on_destruction. In activity_info and activity_policy, don't operate on PRINCIPAL but the invoke activity. Implement thread_activation_collect. When blocking on a futex, don't enqueue the calling thread but the reply messenger. Implement the messenger_id method. (REPLY): Redefine before processing an object invocation to reply using the reply messenger included in the request. * rm.h: Include <l4/message.h>. (rm_method_id_string): Don't handle object_slot_copy_out, object_slot_copy_in, object_slot_read, exception_collect or thread_wait_object_destroyed. Handle object_reply_on_destruction, thread_id, thread_activation_collect. (RPC_TARGET_NEED_ARG): Don't undefine. (RPC_TARGET): Don't define. (struct io_buffer): Redefine in terms of L4_NUM_BRS. (write): Update interface specification according to new IDL interface. Update users. (read): Likewise. (as_dump): Likewise. (fault): Likewise. (RPC_STUB_PREFIX): Don't undefine. (RPC_ID_PREFIX): Likewise. libhurd-mm/ 2008-12-12 Neal H. Walfield <neal@gnu.org> Update to new RPC interface and IPC semantics. Support messengers. * message-buffer.h: New file. * message-buffer.c: Likewise. * Makefile.am (libhurd_mm_a_SOURCES): Add message-buffer.h and message-buffer.c. * headers.m4: Link sysroot/include/hurd/message-buffer.h to libhurd-mm/message-buffer.h. * exceptions.c: Include <hurd/mm.h>, <hurd/rm.h> and <backtrace.h>. (hurd_fault_catcher_register): New function. (hurd_fault_catcher_unregister): Likewise. (hurd_activation_frame_longjmp): Likewise. (utcb_state_save): Rename from this... (l4_utcb_state_save): ... to this. Take a `struct activation_frame *', not a `struct exception_frame *'. (utcb_state_restore): Rename from this... (l4_utcb_state_restore): ... to this. Take a `struct activation_frame *', not a `struct exception_frame *'. (exception_fetch_exception): Rename from this... (hurd_activation_fetch): ... to this. (hurd_activation_message_register): New function. (hurd_activation_frame_longjmp): Likewise. (exception_frame_slab): Rename from this... (activation_frame_slab): ... to this. Use a static initializer. (exception_frame_slab_alloc): Rename from this... (activation_frame_slab_alloc): ... to this. Don't preserve the L4 utcb. (exception_frame_slab_dealloc): Rename from this... (activation_frame_slab_dealloc): ... to this. (exception_frame_alloc): Rename from this... (activation_frame_alloc): ... to this. If there are no preallocated frames, panic. Move the hard allocation code to... (check_activation_frame_reserve): ... this new function. (hurd_activation_stack_dump): New function. (hurd_activation_handler_normal): Take an additional parameter, the utcb. Add consistency checks. Handle IPC and closures. Update fault handling code to use the new fault interface. If unable to resolve the fault via the pager mechanism, see if a fault catcher in installed. Check the UTCB's canary. If running on the alternate stack, clear UTCB->ALTERNATE_STACK_INUSE on exit. (hurd_activation_handler_activated): Take a `struct vg_utcb *', not a `struct exception_page *'. Handle IPC and closures. Improve test to determine if the fault was a stack fault. If so, return to normal mode to handle the fault and use an alternate stack. (activation_handler_area0): New local variable. (activation_handler_msg): Likewise. (initial_utcb): Likewise. (simple_utcb_fetcher): New function. (hurd_utcb): New variable. (hurd_activation_handler_init_early): New function. (hurd_activation_handler_init): Likewise. (exception_handler_init): Remove function. (ACTIVATION_AREA_SIZE_LOG2): Define. (ACTIVATION_AREA_SIZE): Likewise. (hurd_activation_state_alloc): New function. (exception_page_cleanup): Rename from this... (hurd_activation_state_free): ... to this. Rewrite. * ia32-exception-entry.S (_hurd_activation_handler_entry): Save the eflags before executing a sub instruction. Don't try to smartly calculate the location of the UTCB. Instead, just reload it. (activation_frame_run): Use an alternate stack, if requested. Save ebx and ebi. Pass the utcb to the callback. * mm-init.c [i386]: Include <hurd/pager.h>. Include <backtrace.h>. (mm_init): Call hurd_activation_handler_init_early and hurd_activation_handler_init. Don't call exception_handler_init. (mm_init) [! NDEBUG && i386]: Test the activation code. * as-build.c (do_index): Handle indexing a cap_thread or a cap_messenger. (as_build): Likewise. * as-dump.c (do_walk): Handle indexing a cap_thread or a cap_messenger. * as-lookup.c (as_lookup_rel_internal): Likewise. * as.c (as_walk): Likewise. * storage.c: Include <backtrace.h>. (shadow_setup): Update use of rm_folio_object_alloc according to its new interface. (storage_check_reserve_internal): Likewise. (storage_free_): Likewise. (FREE_PAGES_SERIALIZE): Bump to 32. (storage_alloc): If we try to get storage more than 5 lives, print a warning that we may be experiencing live lock. * pager.h (pager_fault_t): Change info's type from `struct exception_info' to `struct activation_fault_info'. (PAGER_VOID): Define. * map.h: Don't include <hurd/exceptions.h>. Include <hurd/as.h>. (maps_lock_lock): Don't use EXCEPTION_STACK_SIZE but AS_STACK_SPACE. (map_fault): Change info's type from `struct exception_info' to `struct activation_fault_info'. * map.c (map_fault): Change info's type from `struct exception_info' to `struct activation_fault_info'. * as.h (AS_STACK_SPACE): Define. (as_lock): Use AS_STACK_SPACE instead of EXCEPTION_STACK_SIZE. (as_lock_readonly): Likewise. * as.h (AS_CHECK_SHADOW): Only check the address translator for capabilities that designate cappages. * anonymous.h (ANONYMOUS_MAGIC): Define. (struct anonymous_pager): Add field magic. * anonymous.c (fault): Assert that ANON->MAGIC has the expected value. Correctly size PAGES. (mdestroy): Assert that ANON->MAGIC has the expected value. (destroy): Likewise. (advise): Likewise. (anonymous_pager_alloc): Initialize ANON->MAGIC. benchmarks/ 2008-12-12 Neal H. Walfield <neal@gnu.org> Update according to new RPC interfaces. * activity-distribution.c (main): Update use of rm_activity_policy and rm_activity_info to be consistent with the new interface. Replace use of `struct exception_info' with `struct activation_fault_info'. * cache.c (helper): Update use of rm_activity_policy and rm_activity_info to be consistent with the new interface. * shared-memory-distribution.c (main): Likewise. hieronymus/ 2008-12-12 Neal H. Walfield <neal@gnu.org> Update according to new RPC interfaces. * hieronymus.c (activity_alloc): Update use of rm_activity_policy, rm_activity_info and rm_folio_object_alloc to be consistent with new interface. Replace use of rm_thread_wait_object_destroyed with rm_object_reply_on_destruction. libc-parts/ 2008-12-11 Neal H. Walfield <neal@gnu.org> Update to new RPC interfaces. * _exit.c (_exit): Update use of rm_folio_object_alloc to be consistent with the new interface. * backtrace.c (RA) [!RM_INTERN]: Set up a fault catch handler to avoid gratuitously faulting. (backtrace) [!RM_INTERN]: Set up a jump buffer. Jump to it on a fault. (backtrace_print): Use s_printf, not printf. * ia32-crt0.S (STACK_SIZE): Increase to 128 kb. * process-spawn.c (process_spawn): Don't use a capability slot to identify the root of the new thread's address space, allocate a thread object. Allocate messengers for the new thread and save them in STARTUP_DATA->MESSENGERS. * s_printf.c (io_buffer_flush): Use the debug output interface. (s_putchar): Don't call rm_write but use io_buffer_flush. libpthread/ 2008-12-11 Neal H. Walfield <neal@gnu.org> Update to new RPC interfaces, IPC semantics. * sysdeps/viengoos/bits/pthread-np.h: Include <hurd/exceptions.h>. (pthread_hurd_utcb_np): New declaration. * sysdeps/viengoos/pt-hurd-utcb-np.c: New file. * Makefile.am (libpthread_a_SOURCES): Add pt-hurd-utcb.c. * sysdeps/viengoos/pt-sysdep.h (EXCEPTION_AREA_SIZE): Don't define. (EXCEPTION_AREA_SIZE_LOG2): Likewise. (EXCEPTION_PAGE): Likewise. (PTHREAD_SYSDEP_MEMBERS): Remove fields exception_area, and exception_area_va. Add fields utcb and lock_message_buffer. * sysdeps/viengoos/pt-thread-alloc.c: Include <hurd/message-buffer.h>. (__pthread_thread_alloc): Initialize thread->lock_message_buffer. When executed the first time, set the thread's L4 user-defined handler. Initialize THREAD->UTCB with the thread's current utcb. Set HURD_UTCB to PTHREAD_HURD_UTCB_NP. For subsequent threads, don't manually set up the activation area. Instead, call hurd_activation_state_alloc. * sysdeps/viengoos/pt-thread-dealloc.c: Include <hurd/message-buffer.h>. (__pthread_thread_dealloc): Call __pthread_thread_halt. Don't manually clean up the activation area. Instead, call hurd_activation_state_free. Free THREAD->LOCK_MESSAGE_BUFFER. * sysdeps/viengoos/ia32/pt-setup.c (stack_setup): Pre-fault the first four pages of the new stack. (__pthread_setup): Don't set up the activation area. * sysdeps/viengoos/pt-wakeup.c (__pthread_wakeup): Use futex_wake_using with the calling thread's lock messenger. * sysdeps/viengoos/pt-block.c (__pthread_block): Use futex_wait_using and provide THREAD->LOCK_MESSAGE_BUFFER as the message buffer. * sysdeps/viengoos/pt-thread-start.c (__pthread_thread_start): Don't set the first thread's L4 user-defined handler here. (__pthread_thread_start): Update use of rm_thread_exregs according to be consistent with new interface. * sysdeps/viengoos/pt-thread-halt.c (__pthread_thread_halt): If THREAD is the current thread, call vg_suspend. * sysdeps/viengoos/pt-setactivity-np.c (pthread_setactivity_np): Update use of rm_thread_exregs according to be consistent with new interface. * sysdeps/viengoos/ia32/signal-dispatch-lowlevel.c (signal_dispatch_lowlevel): Use __builtin_frame_address to get the current stack frame's start. Update use of rm_thread_exregs according to be consistent with new interface. ruth/ 2008-12-12 Neal H. Walfield <neal@gnu.org> Update to new RPC interfaces. * ruth.c (main): Update use of rm_folio_alloc, rm_folio_object_alloc, rm_thread_exregs, rm_activity_policy, rm_activity_info. Replace use of rm_thread_wait_object_destroy with rm_object_reply_on_destruction. Replace use of `struct exception_info' with `struct activation_fault_info'. Fix signal test's use of condition variables to not rely on the scheduler. When checking deallocation code, set up a fault handler to programmatically determine success.
Diffstat (limited to 'hurd/rpc.h')
-rw-r--r--hurd/rpc.h1041
1 files changed, 669 insertions, 372 deletions
diff --git a/hurd/rpc.h b/hurd/rpc.h
index e363509..55fe8be 100644
--- a/hurd/rpc.h
+++ b/hurd/rpc.h
@@ -4,20 +4,19 @@
This file is part of the GNU Hurd.
- The GNU Hurd 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.
+ GNU Hurd 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 3 of the
+ License, or (at your option) any later version.
- The GNU Hurd is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
+ GNU Hurd 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 the GNU C Library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
- 02111-1307 USA. */
+ License along with GNU Hurd. If not, see
+ <http://www.gnu.org/licenses/>. */
#define RPC_CONCAT2(a,b) a##b
#define RPC_CONCAT(a,b) RPC_CONCAT2(a,b)
@@ -41,107 +40,66 @@
#else
#define RPC_ID_PREFIX_(name) RPC_CONCAT(RPC_ID_PREFIX,_##name)
#endif
-
-/* We need to know where to send the IPC. Either the caller can
- supply it or it can be implicit.
-
- If the caller should supply the target, then define
- RPC_TARGET_NEED_ARG, RPC_TARGET_ARG_TYPE to the type of the
- argument, and RPC_TARGET to a be a macro that takes a single
- argument and returns an l4_thread_id_t.
-
- #define RPC_STUB_PREFIX prefix
- #define RPC_ID_PREFIX PREFIX
- #define RPC_TARGET_NEED_ARG
- #define RPC_TARGET_ARG_TYPE object_t
- #define RPC_TARGET(x) ((x)->thread_id)
-
- If the caller need not supply the argument, then the includer
- should not define RPC_TARGET_NEED_ARG and should define RPC_TARGET
- to be a macro that takes no arguments and returns an
- l4_thread_id_t.
-
- #define RPC_STUB_PREFIX prefix
- #define RPC_ID_PREFIX PREFIX
- #undef RPC_TARGET_NEED_ARG
- #define RPC_TARGET ({ extern l4_thread_id_t foo_server; foo_server; })
-
- At the end of the include file, be sure to #undef the used
- preprocessor variables to avoid problems when multiple headers
- make use of this file.
-
- #undef RPC_STUB_PREFIX
- #undef RPC_ID_PREFIX
- #undef RPC_TARGET_NEED_ARG
- #undef RPC_TARGET_ARG_TYPE
- #undef RPC_TARGET
- */
-#ifndef RPC_TARGET
-#error Did not define RPC_TARGET
-#endif
-
-#undef RPC_TARGET_ARG_
-#undef RPC_TARGET_
-
-#ifdef RPC_TARGET_NEED_ARG
-# ifndef RPC_TARGET_ARG_TYPE
-# error RPC_TARGET_NEED_ARG define but RPC_TARGET_ARG_TYPE not defined.
-# endif
-
-# define RPC_TARGET_ARG_ RPC_TARGET_ARG_TYPE arg_,
-# define RPC_TARGET_ RPC_TARGET(arg_)
-#else
-
-# define RPC_TARGET_ARG_
-# define RPC_TARGET_ RPC_TARGET
-#endif
-
-#undef RPC_TARGET_NEED_ARG
#ifndef _HURD_RPC_H
#define _HURD_RPC_H
#include <hurd/stddef.h>
-#include <l4/ipc.h>
-#include <l4/space.h>
+#include <hurd/message.h>
+#include <hurd/ipc.h>
#include <errno.h>
+
+#ifdef RM_INTERN
+extern struct vg_message *reply_buffer;
+
+/* We can't include messenger.h as it includes hurd/cap.h which in turn
+ includes this file. */
+struct messenger;
+struct activity;
+extern bool messenger_message_load (struct activity *activity,
+ struct messenger *target,
+ struct vg_message *message);
+#else
+# include <hurd/message-buffer.h>
+#endif
+typedef addr_t cap_t;
/* First we define some cpp help macros. */
-#define CPP_IFTHEN_0(when, whennot) whennot
-#define CPP_IFTHEN_1(when, whennot) when
-#define CPP_IFTHEN_2(when, whennot) when
-#define CPP_IFTHEN_3(when, whennot) when
-#define CPP_IFTHEN_4(when, whennot) when
-#define CPP_IFTHEN_5(when, whennot) when
-#define CPP_IFTHEN_6(when, whennot) when
-#define CPP_IFTHEN_7(when, whennot) when
-#define CPP_IFTHEN_8(when, whennot) when
-#define CPP_IFTHEN_9(when, whennot) when
-#define CPP_IFTHEN_10(when, whennot) when
-#define CPP_IFTHEN_11(when, whennot) when
-#define CPP_IFTHEN_12(when, whennot) when
-#define CPP_IFTHEN_13(when, whennot) when
-#define CPP_IFTHEN_14(when, whennot) when
-#define CPP_IFTHEN_15(when, whennot) when
-#define CPP_IFTHEN_16(when, whennot) when
-#define CPP_IFTHEN_17(when, whennot) when
-#define CPP_IFTHEN_18(when, whennot) when
-#define CPP_IFTHEN_19(when, whennot) when
-#define CPP_IFTHEN_20(when, whennot) when
-#define CPP_IFTHEN_21(when, whennot) when
-#define CPP_IFTHEN_22(when, whennot) when
-#define CPP_IFTHEN_23(when, whennot) when
-#define CPP_IFTHEN_24(when, whennot) when
-#define CPP_IFTHEN_25(when, whennot) when
-
-#define CPP_IFTHEN_(expr, when, whennot) \
- CPP_IFTHEN_##expr(when, whennot)
-#define CPP_IFTHEN(expr, when, whennot) \
- CPP_IFTHEN_(expr, when, whennot)
-#define CPP_IF(expr, when) \
- CPP_IFTHEN(expr, when,)
-#define CPP_IFNOT(expr, whennot) \
- CPP_IFTHEN(expr, , whennot)
+#define CPP_IFELSE_0(when, whennot) whennot
+#define CPP_IFELSE_1(when, whennot) when
+#define CPP_IFELSE_2(when, whennot) when
+#define CPP_IFELSE_3(when, whennot) when
+#define CPP_IFELSE_4(when, whennot) when
+#define CPP_IFELSE_5(when, whennot) when
+#define CPP_IFELSE_6(when, whennot) when
+#define CPP_IFELSE_7(when, whennot) when
+#define CPP_IFELSE_8(when, whennot) when
+#define CPP_IFELSE_9(when, whennot) when
+#define CPP_IFELSE_10(when, whennot) when
+#define CPP_IFELSE_11(when, whennot) when
+#define CPP_IFELSE_12(when, whennot) when
+#define CPP_IFELSE_13(when, whennot) when
+#define CPP_IFELSE_14(when, whennot) when
+#define CPP_IFELSE_15(when, whennot) when
+#define CPP_IFELSE_16(when, whennot) when
+#define CPP_IFELSE_17(when, whennot) when
+#define CPP_IFELSE_18(when, whennot) when
+#define CPP_IFELSE_19(when, whennot) when
+#define CPP_IFELSE_20(when, whennot) when
+#define CPP_IFELSE_21(when, whennot) when
+#define CPP_IFELSE_22(when, whennot) when
+#define CPP_IFELSE_23(when, whennot) when
+#define CPP_IFELSE_24(when, whennot) when
+#define CPP_IFELSE_25(when, whennot) when
+
+#define CPP_IFELSE_(expr, when, whennot) \
+ CPP_IFELSE_##expr(when, whennot)
+#define CPP_IFELSE(expr, when, whennot) \
+ CPP_IFELSE_(expr, when, whennot)
+#define CPP_IF(expr, when) \
+ CPP_IFELSE(expr, when,)
+#define CPP_IFNOT(expr, whennot) \
+ CPP_IFELSE(expr, , whennot)
#define CPP_SUCC_0 1
#define CPP_SUCC_1 2
@@ -176,11 +134,11 @@
/* We'd like to define CPP_ADD as:
#define CPP_ADD(x, y) \
- CPP_IFTHEN(y, CPP_ADD(SUCC(x), SUCC(y)), y)
+ CPP_IFELSE(y, CPP_ADD(SUCC(x), SUCC(y)), y)
This does not work as while a macro is being expanded, it becomes
ineligible for expansion. Thus, any references (including indirect
- references) are not expanded. Nested applications of a macro are,
+ references) are not expanded. Repeated applications of a macro are,
however, allowed, and this is what the CPP_APPLY macro does. */
#define CPP_APPLY1(x, y) x(y)
#define CPP_APPLY2(x, y) x(CPP_APPLY1(x, y))
@@ -209,13 +167,44 @@
#define CPP_APPLY25(x, y) x(CPP_APPLY24(x, y))
#define CPP_ADD(x, y) \
- CPP_IFTHEN(y, CPP_APPLY##y(CPP_SUCC, x), x)
+ CPP_IFELSE(y, CPP_APPLY##y(CPP_SUCC, x), x)
+
+/* Apply a function to each of the first n arguments.
+
+
+ CPP_FOREACH(2, CPP_SAFE_DEREF, NULL, a, b)
+
+ =>
+
+ ((a) ? *(a) : NULL), ((b) ? *(b) : NULL)
+ */
+#define CPP_FOREACH_0(func, cookie, ...)
+#define CPP_FOREACH_1(func, cookie, element, ...) func(cookie, element)
+#define CPP_FOREACH_2(func, cookie, element, ...) func(cookie, element), CPP_FOREACH_1(func, cookie, __VA_ARGS__)
+#define CPP_FOREACH_3(func, cookie, element, ...) func(cookie, element), CPP_FOREACH_2(func, cookie, __VA_ARGS__)
+#define CPP_FOREACH_4(func, cookie, element, ...) func(cookie, element), CPP_FOREACH_3(func, cookie, __VA_ARGS__)
+#define CPP_FOREACH_5(func, cookie, element, ...) func(cookie, element), CPP_FOREACH_4(func, cookie, __VA_ARGS__)
+#define CPP_FOREACH_6(func, cookie, element, ...) func(cookie, element), CPP_FOREACH_5(func, cookie, __VA_ARGS__)
+#define CPP_FOREACH_7(func, cookie, element, ...) func(cookie, element), CPP_FOREACH_6(func, cookie, __VA_ARGS__)
+#define CPP_FOREACH_8(func, cookie, element, ...) func(cookie, element), CPP_FOREACH_7(func, cookie, __VA_ARGS__)
+#define CPP_FOREACH_9(func, cookie, element, ...) func(cookie, element), CPP_FOREACH_8(func, cookie, __VA_ARGS__)
+
+#define CPP_FOREACH_(n, func, cookie, ...) \
+ CPP_FOREACH_##n(func, cookie, __VA_ARGS__)
+#define CPP_FOREACH(n, func, cookie, ...) \
+ CPP_FOREACH_(n, func, cookie, __VA_ARGS__)
+
+/* Used in conjunction with CPP_FOREACH. Generates C code that
+ dereferences ELEMENT if it is not NULL, otherwise, returns
+ COOKIE. */
+#define CPP_SAFE_DEREF(cookie, element) ((element) ? *(element) : (cookie))
+
/* CPP treats commas specially so we have to be smart about how we
insert them algorithmically. For instance, this won't work:
#define COMMA ,
- CPP_IFTHEN(x, COMMA, )
+ CPP_IFELSE(x, COMMA, )
To optional insert a comma, use this function instead. When the
result is need, invoke the result. For instance:
@@ -224,22 +213,36 @@
*/
#define RPC_COMMA() ,
#define RPC_NOCOMMA()
-#define RPC_IF_COMMA(x) CPP_IFTHEN(x, RPC_COMMA, RPC_NOCOMMA)
+#define RPC_IF_COMMA(x) CPP_IFELSE(x, RPC_COMMA, RPC_NOCOMMA)
-/* Load the argument ARG, which is of type TYPE into MR IDX. */
+/* Append the argument __RLA_ARG, whose type is __RLA_TYPE, to the
+ message buffer MSG. */
#define RPCLOADARG(__rla_type, __rla_arg) \
{ \
- union \
- { \
- __rla_type __rla_a; \
- l4_word_t __rla_raw[(sizeof (__rla_type) + sizeof (l4_word_t) - 1) \
- / sizeof (l4_word_t)]; \
- } __rla_arg2 = { (__rla_arg) }; \
- int __rla_i; \
- for (__rla_i = 0; \
- __rla_i < sizeof (__rla_arg2) / sizeof (l4_word_t); \
- __rla_i ++) \
- l4_msg_append_word (*msg, __rla_arg2.__rla_raw[__rla_i]); \
+ if (__builtin_strcmp (#__rla_type, "cap_t") == 0) \
+ { \
+ union \
+ { \
+ __rla_type __rla_a; \
+ RPC_GRAB2 (, 1, RPC_TYPE_SHIFT (1, struct cap *, cap_t, __rla_foo)); \
+ cap_t __rla_cap; \
+ } __rla_arg2 = { (__rla_arg) }; \
+ vg_message_append_cap (msg, __rla_arg2.__rla_cap); \
+ } \
+ else \
+ { \
+ union \
+ { \
+ __rla_type __rla_a; \
+ uintptr_t __rla_raw[(sizeof (__rla_type) + sizeof (uintptr_t) - 1) \
+ / sizeof (uintptr_t)]; \
+ } __rla_arg2 = { (__rla_arg) }; \
+ int __rla_i; \
+ for (__rla_i = 0; \
+ __rla_i < sizeof (__rla_arg2) / sizeof (uintptr_t); \
+ __rla_i ++) \
+ vg_message_append_word (msg, __rla_arg2.__rla_raw[__rla_i]); \
+ } \
}
#define RPCLOAD0(...)
@@ -271,23 +274,48 @@
#define RPCLOAD_(__rl_count, ...) RPCLOAD##__rl_count (__VA_ARGS__)
#define RPCLOAD(__rl_count, ...) RPCLOAD_ (__rl_count, __VA_ARGS__)
-/* Store the contents of MR __RSU_IDX+1 into *ARG, which is of type TYPE.
- NB: __RSU_IDX is thus the return parameter number, not the message
- register number; MR0 contains the error code. */
+/* Store the next argument in the message MSG whose type is __RSA_TYPE
+ in *__RSA_ARG. */
#define RPCSTOREARG(__rsa_type, __rsa_arg) \
{ \
- union \
- { \
- __rsa_type __rsa_a; \
- l4_word_t __rsa_raw[(sizeof (__rsa_type) + sizeof (l4_word_t) - 1) \
- / sizeof (l4_word_t)]; \
- } __rsa_arg2; \
- int __rsa_i; \
- for (__rsa_i = 0; \
- __rsa_i < sizeof (__rsa_arg2) / sizeof (l4_word_t); \
- __rsa_i ++) \
- __rsa_arg2.__rsa_raw[__rsa_i] = l4_msg_word (*msg, __rsu_idx ++); \
- *(__rsa_arg) = __rsa_arg2.__rsa_a; \
+ if (__builtin_strcmp (#__rsa_type, "cap_t") == 0) \
+ { \
+ union \
+ { \
+ __rsa_type *__rsa_a; \
+ cap_t *__rsa_cap; \
+ } __rsa_arg2; \
+ __rsa_arg2.__rsa_a = __rsa_arg; \
+ if (vg_message_cap_count (msg) > __rsu_cap_idx) \
+ { \
+ if (__rsa_arg) \
+ *__rsa_arg2.__rsa_cap = vg_message_cap (msg, __rsu_cap_idx); \
+ __rsu_cap_idx ++; \
+ } \
+ else \
+ __rsu_err = EINVAL; \
+ } \
+ else \
+ { \
+ union \
+ { \
+ __rsa_type __rsa_a; \
+ uintptr_t __rsa_raw[(sizeof (__rsa_type) + sizeof (uintptr_t) - 1) \
+ / sizeof (uintptr_t)]; \
+ } __rsa_arg2; \
+ int __rsa_i; \
+ for (__rsa_i = 0; \
+ __rsa_i < sizeof (__rsa_arg2) / sizeof (uintptr_t); \
+ __rsa_i ++) \
+ if (vg_message_data_count (msg) / sizeof (uintptr_t) \
+ > __rsu_data_idx) \
+ __rsa_arg2.__rsa_raw[__rsa_i] \
+ = vg_message_word (msg, __rsu_data_idx ++); \
+ else \
+ __rsu_err = EINVAL; \
+ if (! __rsu_err && __rsa_arg) \
+ *(__rsa_arg) = __rsa_arg2.__rsa_a; \
+ } \
}
#define RPCSTORE0(...)
@@ -345,35 +373,36 @@
#define RPCSTORE_(__rs_count, ...) RPCSTORE##__rs_count (__VA_ARGS__)
#define RPCSTORE(__rs_count, ...) RPCSTORE_ (__rs_count, __VA_ARGS__)
-/* Marshal the in-arguments into the provided message buffer. */
+/* Marshal a request. */
#define RPC_SEND_MARSHAL(id, icount, ...) \
static inline void \
+ __attribute__((always_inline)) \
RPC_CONCAT (RPC_STUB_PREFIX_(id), _send_marshal) \
- (l4_msg_t *msg RPC_IF_COMMA (icount) () \
- RPC_GRAB2 (, icount, ##__VA_ARGS__)) \
+ (struct vg_message *msg, \
+ RPC_GRAB2 (, icount, ##__VA_ARGS__) RPC_IF_COMMA(icount) () \
+ cap_t reply_messenger) \
{ \
- l4_msg_tag_t tag; \
- \
- tag = l4_niltag; \
- l4_msg_tag_set_label (&tag, RPC_ID_PREFIX_(id)); \
- \
- l4_msg_clear (*msg); \
- l4_msg_set_msg_tag (*msg, tag); \
- \
+ vg_message_clear (msg); \
+ /* Add the label. */ \
+ vg_message_append_word (msg, RPC_ID_PREFIX_(id)); \
+ /* Then load the arguments. */ \
RPCLOAD (icount, ##__VA_ARGS__); \
+ /* Finally, add the reply messenger. */ \
+ vg_message_append_cap (msg, reply_messenger); \
}
-/* Unmarshal the in-arguments from the provided message buffer. */
+/* Unmarshal a request. */
#define RPC_SEND_UNMARSHAL(id, icount, ...) \
static inline error_t \
+ __attribute__((always_inline)) \
RPC_CONCAT (RPC_STUB_PREFIX_(id), _send_unmarshal) \
- (l4_msg_t *msg RPC_IF_COMMA(icount) () \
- RPC_GRAB2 (*, icount, ##__VA_ARGS__)) \
+ (struct vg_message *msg, \
+ RPC_GRAB2 (*, icount, ##__VA_ARGS__) RPC_IF_COMMA(icount) () \
+ cap_t *reply_messenger) \
{ \
- l4_msg_tag_t tag = l4_msg_msg_tag (*msg); \
- \
- l4_word_t label; \
- label = l4_label (tag); \
+ uintptr_t label = 0; \
+ if (likely (vg_message_data_count (msg) >= sizeof (uintptr_t))) \
+ label = vg_message_word (msg, 0); \
if (label != RPC_ID_PREFIX_(id)) \
{ \
debug (1, #id " has bad method id, %d, excepted %d", \
@@ -381,130 +410,175 @@
return EINVAL; \
} \
\
- error_t err = 0; \
- int __rsu_idx __attribute__ ((unused)); \
- __rsu_idx = 0; \
+ int __rsu_data_idx __attribute__ ((unused)) = 1; \
+ int __rsu_cap_idx __attribute__ ((unused)) = 0; \
+ error_t __rsu_err = 0; \
RPCSTORE (icount, ##__VA_ARGS__); \
- if (err == 0 && __rsu_idx != l4_untyped_words (tag)) \
+ if (unlikely (__rsu_err \
+ || (__rsu_data_idx * sizeof (uintptr_t) \
+ != vg_message_data_count (msg) \
+ && __rsu_cap_idx + 1 != vg_message_cap_count (msg)))) \
{ \
- debug (1, #id " has wrong number of arguments: %d, expected %d words", \
- l4_untyped_words (tag), __rsu_idx); \
+ debug (1, #id " has wrong number of arguments: " \
+ "got %d bytes and %d caps; expected %d/%d", \
+ __rsu_data_idx * sizeof (uintptr_t), __rsu_cap_idx + 1, \
+ vg_message_data_count (msg), \
+ vg_message_cap_count (msg)); \
return EINVAL; \
} \
+ \
+ if (reply_messenger) \
+ *reply_messenger = vg_message_cap (msg, __rsu_cap_idx); \
return 0; \
}
-/* Marshal the reply. */
-#define RPC_REPLY_MARSHAL(id, ocount, ...) \
+/* Prepare a receive buffer. */
+#ifdef RM_INTERN
+#define RPC_RECEIVE_MARSHAL(id, ret_cap_count, ...)
+#else
+#define RPC_RECEIVE_MARSHAL(id, ret_cap_count, ...) \
+ static inline void \
+ __attribute__((always_inline)) \
+ RPC_CONCAT (RPC_STUB_PREFIX_(id), _receive_marshal) \
+ (struct vg_message *msg RPC_IF_COMMA(ret_cap_count) () \
+ RPC_GRAB2 (, ret_cap_count, ##__VA_ARGS__)) \
+ { \
+ vg_message_clear (msg); \
+ /* Load the arguments. */ \
+ RPCLOAD (ret_cap_count, ##__VA_ARGS__); \
+ assert (vg_message_data_count (msg) == 0); \
+ assert (vg_message_cap_count (msg) == ret_cap_count); \
+ }
+#endif
+
+/* Marshal a reply. */
+#define RPC_REPLY_MARSHAL(id, out_count, ret_cap_count, ...) \
static inline void \
+ __attribute__((always_inline)) \
RPC_CONCAT (RPC_STUB_PREFIX_(id), _reply_marshal) \
- (l4_msg_t *msg RPC_IF_COMMA (ocount) () \
- RPC_GRAB2 (, ocount, ##__VA_ARGS__)) \
+ (struct vg_message *msg \
+ RPC_IF_COMMA (out_count) () \
+ RPC_GRAB2 (, out_count, ##__VA_ARGS__) \
+ RPC_IF_COMMA (ret_cap_count) () \
+ RPC_GRAB2 (, ret_cap_count, \
+ RPC_TYPE_SHIFT (ret_cap_count, struct cap *, \
+ RPC_CHOP2 (out_count, __VA_ARGS__)))) \
{ \
- l4_msg_tag_t tag; \
- \
- tag = l4_niltag; \
- l4_msg_tag_set_label (&tag, RPC_ID_PREFIX_(id)); \
+ vg_message_clear (msg); \
\
- l4_msg_clear (*msg); \
- l4_msg_set_msg_tag (*msg, tag); \
+ /* The error code. */ \
+ vg_message_append_word (msg, 0); \
+ RPCLOAD (CPP_ADD (out_count, ret_cap_count), ##__VA_ARGS__); \
\
- /* No error. */ \
- l4_msg_append_word (*msg, 0); \
- \
- RPCLOAD (ocount, ##__VA_ARGS__); \
+ assert (vg_message_cap_count (msg) == ret_cap_count); \
}
-/* Unmarshal the reply. */
-#define RPC_REPLY_UNMARSHAL(id, ocount, ...) \
+/* Unmarshal a reply. */
+#define RPC_REPLY_UNMARSHAL(id, out_count, ret_cap_count, ...) \
static inline error_t \
+ __attribute__((always_inline)) \
RPC_CONCAT (RPC_STUB_PREFIX_(id), _reply_unmarshal) \
- (l4_msg_t *msg RPC_IF_COMMA (ocount) () \
- RPC_GRAB2(*, ocount, ##__VA_ARGS__)) \
+ (struct vg_message *msg \
+ RPC_IF_COMMA (CPP_ADD (out_count, ret_cap_count)) () \
+ RPC_GRAB2(*, CPP_ADD (out_count, ret_cap_count), ##__VA_ARGS__)) \
{ \
- l4_msg_tag_t tag = l4_msg_msg_tag (*msg); \
- l4_word_t err = l4_msg_word (*msg, 0); \
+ /* The server error code. */ \
+ error_t __rsu_err = EINVAL; \
+ if (likely (vg_message_data_count (msg) >= sizeof (uintptr_t))) \
+ __rsu_err = vg_message_word (msg, 0); \
+ if (unlikely (__rsu_err)) \
+ return __rsu_err; \
\
- int __rsu_idx __attribute__ ((unused)); \
- __rsu_idx = 1; \
- RPCSTORE (ocount, ##__VA_ARGS__); \
- if (err == 0) \
+ int __rsu_data_idx __attribute__ ((unused)) = 1; \
+ int __rsu_cap_idx __attribute__ ((unused)) = 0; \
+ RPCSTORE (CPP_ADD (out_count, ret_cap_count), ##__VA_ARGS__); \
+ if (unlikely (__rsu_err \
+ || (__rsu_data_idx * sizeof (uintptr_t) \
+ != vg_message_data_count (msg) \
+ || __rsu_cap_idx != vg_message_cap_count (msg)))) \
{ \
- if (__rsu_idx != l4_untyped_words (tag)) \
- { \
- debug (1, "Got %d words, expected %d words", \
- __rsu_idx, l4_untyped_words (tag)); \
- return EINVAL; \
- } \
+ debug (1, #id " has wrong number of arguments: " \
+ "got %d bytes and %d caps; expected %d/%d", \
+ __rsu_data_idx * sizeof (uintptr_t), __rsu_cap_idx, \
+ vg_message_data_count (msg), \
+ vg_message_cap_count (msg)); \
+ return EINVAL; \
} \
- return err; \
+ return 0; \
}
/* RPC_ARGUMENTS takes a list of types and arguments and returns the first
COUNT arguments. (NB: the list may contain more than COUNT
- arguments!). */
+ arguments!).
+
+ RPC_ARGUMENTS(2, &, int, i, int, j, double, d)
+
+ =>
+
+ &i, &j
+*/
#define RPC_ARGUMENTS0(...)
-#define RPC_ARGUMENTS1(__ra_type, __ra_arg, ...) __ra_arg RPC_ARGUMENTS0(__VA_ARGS__)
-#define RPC_ARGUMENTS2(__ra_type, __ra_arg, ...) __ra_arg, RPC_ARGUMENTS1(__VA_ARGS__)
-#define RPC_ARGUMENTS3(__ra_type, __ra_arg, ...) __ra_arg, RPC_ARGUMENTS2(__VA_ARGS__)
-#define RPC_ARGUMENTS4(__ra_type, __ra_arg, ...) __ra_arg, RPC_ARGUMENTS3(__VA_ARGS__)
-#define RPC_ARGUMENTS5(__ra_type, __ra_arg, ...) __ra_arg, RPC_ARGUMENTS4(__VA_ARGS__)
-#define RPC_ARGUMENTS6(__ra_type, __ra_arg, ...) __ra_arg, RPC_ARGUMENTS5(__VA_ARGS__)
-#define RPC_ARGUMENTS7(__ra_type, __ra_arg, ...) __ra_arg, RPC_ARGUMENTS6(__VA_ARGS__)
-#define RPC_ARGUMENTS8(__ra_type, __ra_arg, ...) __ra_arg, RPC_ARGUMENTS7(__VA_ARGS__)
-#define RPC_ARGUMENTS9(__ra_type, __ra_arg, ...) __ra_arg, RPC_ARGUMENTS8(__VA_ARGS__)
-#define RPC_ARGUMENTS10(__ra_type, __ra_arg, ...) __ra_arg, RPC_ARGUMENTS9(__VA_ARGS__)
-#define RPC_ARGUMENTS11(__ra_type, __ra_arg, ...) __ra_arg, RPC_ARGUMENTS10(__VA_ARGS__)
-#define RPC_ARGUMENTS12(__ra_type, __ra_arg, ...) __ra_arg, RPC_ARGUMENTS11(__VA_ARGS__)
-#define RPC_ARGUMENTS13(__ra_type, __ra_arg, ...) __ra_arg, RPC_ARGUMENTS12(__VA_ARGS__)
-#define RPC_ARGUMENTS14(__ra_type, __ra_arg, ...) __ra_arg, RPC_ARGUMENTS13(__VA_ARGS__)
-#define RPC_ARGUMENTS15(__ra_type, __ra_arg, ...) __ra_arg, RPC_ARGUMENTS14(__VA_ARGS__)
-#define RPC_ARGUMENTS16(__ra_type, __ra_arg, ...) __ra_arg, RPC_ARGUMENTS15(__VA_ARGS__)
-#define RPC_ARGUMENTS17(__ra_type, __ra_arg, ...) __ra_arg, RPC_ARGUMENTS16(__VA_ARGS__)
-#define RPC_ARGUMENTS18(__ra_type, __ra_arg, ...) __ra_arg, RPC_ARGUMENTS17(__VA_ARGS__)
-#define RPC_ARGUMENTS19(__ra_type, __ra_arg, ...) __ra_arg, RPC_ARGUMENTS18(__VA_ARGS__)
-#define RPC_ARGUMENTS20(__ra_type, __ra_arg, ...) __ra_arg, RPC_ARGUMENTS19(__VA_ARGS__)
-#define RPC_ARGUMENTS_(__ra_count, ...) RPC_ARGUMENTS##__ra_count(__VA_ARGS__)
-#define RPC_ARGUMENTS(__ra_count, ...) RPC_ARGUMENTS_(__ra_count, __VA_ARGS__)
+#define RPC_ARGUMENTS1(__ra_prefix, __ra_type, __ra_arg, ...) __ra_prefix __ra_arg RPC_ARGUMENTS0(__ra_prefix, __VA_ARGS__)
+#define RPC_ARGUMENTS2(__ra_prefix, __ra_type, __ra_arg, ...) __ra_prefix __ra_arg, RPC_ARGUMENTS1(__ra_prefix, __VA_ARGS__)
+#define RPC_ARGUMENTS3(__ra_prefix, __ra_type, __ra_arg, ...) __ra_prefix __ra_arg, RPC_ARGUMENTS2(__ra_prefix, __VA_ARGS__)
+#define RPC_ARGUMENTS4(__ra_prefix, __ra_type, __ra_arg, ...) __ra_prefix __ra_arg, RPC_ARGUMENTS3(__ra_prefix, __VA_ARGS__)
+#define RPC_ARGUMENTS5(__ra_prefix, __ra_type, __ra_arg, ...) __ra_prefix __ra_arg, RPC_ARGUMENTS4(__ra_prefix, __VA_ARGS__)
+#define RPC_ARGUMENTS6(__ra_prefix, __ra_type, __ra_arg, ...) __ra_prefix __ra_arg, RPC_ARGUMENTS5(__ra_prefix, __VA_ARGS__)
+#define RPC_ARGUMENTS7(__ra_prefix, __ra_type, __ra_arg, ...) __ra_prefix __ra_arg, RPC_ARGUMENTS6(__ra_prefix, __VA_ARGS__)
+#define RPC_ARGUMENTS8(__ra_prefix, __ra_type, __ra_arg, ...) __ra_prefix __ra_arg, RPC_ARGUMENTS7(__ra_prefix, __VA_ARGS__)
+#define RPC_ARGUMENTS9(__ra_prefix, __ra_type, __ra_arg, ...) __ra_prefix __ra_arg, RPC_ARGUMENTS8(__ra_prefix, __VA_ARGS__)
+#define RPC_ARGUMENTS10(__ra_prefix, __ra_type, __ra_arg, ...) __ra_prefix __ra_arg, RPC_ARGUMENTS9(__ra_prefix, __VA_ARGS__)
+#define RPC_ARGUMENTS11(__ra_prefix, __ra_type, __ra_arg, ...) __ra_prefix __ra_arg, RPC_ARGUMENTS10(__ra_prefix, __VA_ARGS__)
+#define RPC_ARGUMENTS12(__ra_prefix, __ra_type, __ra_arg, ...) __ra_prefix __ra_arg, RPC_ARGUMENTS11(__ra_prefix, __VA_ARGS__)
+#define RPC_ARGUMENTS13(__ra_prefix, __ra_type, __ra_arg, ...) __ra_prefix __ra_arg, RPC_ARGUMENTS12(__ra_prefix, __VA_ARGS__)
+#define RPC_ARGUMENTS14(__ra_prefix, __ra_type, __ra_arg, ...) __ra_prefix __ra_arg, RPC_ARGUMENTS13(__ra_prefix, __VA_ARGS__)
+#define RPC_ARGUMENTS15(__ra_prefix, __ra_type, __ra_arg, ...) __ra_prefix __ra_arg, RPC_ARGUMENTS14(__ra_prefix, __VA_ARGS__)
+#define RPC_ARGUMENTS16(__ra_prefix, __ra_type, __ra_arg, ...) __ra_prefix __ra_arg, RPC_ARGUMENTS15(__ra_prefix, __VA_ARGS__)
+#define RPC_ARGUMENTS17(__ra_prefix, __ra_type, __ra_arg, ...) __ra_prefix __ra_arg, RPC_ARGUMENTS16(__ra_prefix, __VA_ARGS__)
+#define RPC_ARGUMENTS18(__ra_prefix, __ra_type, __ra_arg, ...) __ra_prefix __ra_arg, RPC_ARGUMENTS17(__ra_prefix, __VA_ARGS__)
+#define RPC_ARGUMENTS19(__ra_prefix, __ra_type, __ra_arg, ...) __ra_prefix __ra_arg, RPC_ARGUMENTS18(__ra_prefix, __VA_ARGS__)
+#define RPC_ARGUMENTS20(__ra_prefix, __ra_type, __ra_arg, ...) __ra_prefix __ra_arg, RPC_ARGUMENTS19(__ra_prefix, __VA_ARGS__)
+#define RPC_ARGUMENTS_(__ra_count, __ra_prefix, ...) RPC_ARGUMENTS##__ra_count(__ra_prefix, __VA_ARGS__)
+#define RPC_ARGUMENTS(__ra_count, __ra_prefix, ...) RPC_ARGUMENTS_(__ra_count, __ra_prefix, __VA_ARGS__)
/* Given a list of arguments, returns the arguments minus the first
COUNT **pairs** of arguments. For example:
- RPC_CHOP(1, int, i, int, j, double, d)
+ RPC_CHOP2(1, int, i, int, j, double, d)
=>
int, j, double, d
*/
-#define RPC_CHOP0(...) __VA_ARGS__
-#define RPC_CHOP1(__rc_a, __rc_b, ...) RPC_CHOP0(__VA_ARGS__)
-#define RPC_CHOP2(__rc_a, __rc_b, ...) RPC_CHOP1(__VA_ARGS__)
-#define RPC_CHOP3(__rc_a, __rc_b, ...) RPC_CHOP2(__VA_ARGS__)
-#define RPC_CHOP4(__rc_a, __rc_b, ...) RPC_CHOP3(__VA_ARGS__)
-#define RPC_CHOP5(__rc_a, __rc_b, ...) RPC_CHOP4(__VA_ARGS__)
-#define RPC_CHOP6(__rc_a, __rc_b, ...) RPC_CHOP5(__VA_ARGS__)
-#define RPC_CHOP7(__rc_a, __rc_b, ...) RPC_CHOP6(__VA_ARGS__)
-#define RPC_CHOP8(__rc_a, __rc_b, ...) RPC_CHOP7(__VA_ARGS__)
-#define RPC_CHOP9(__rc_a, __rc_b, ...) RPC_CHOP8(__VA_ARGS__)
-#define RPC_CHOP10(__rc_a, __rc_b, ...) RPC_CHOP9(__VA_ARGS__)
-#define RPC_CHOP11(__rc_a, __rc_b, ...) RPC_CHOP10(__VA_ARGS__)
-#define RPC_CHOP12(__rc_a, __rc_b, ...) RPC_CHOP11(__VA_ARGS__)
-#define RPC_CHOP13(__rc_a, __rc_b, ...) RPC_CHOP12(__VA_ARGS__)
-#define RPC_CHOP14(__rc_a, __rc_b, ...) RPC_CHOP13(__VA_ARGS__)
-#define RPC_CHOP15(__rc_a, __rc_b, ...) RPC_CHOP14(__VA_ARGS__)
-#define RPC_CHOP16(__rc_a, __rc_b, ...) RPC_CHOP15(__VA_ARGS__)
-#define RPC_CHOP17(__rc_a, __rc_b, ...) RPC_CHOP16(__VA_ARGS__)
-#define RPC_CHOP18(__rc_a, __rc_b, ...) RPC_CHOP17(__VA_ARGS__)
-#define RPC_CHOP19(__rc_a, __rc_b, ...) RPC_CHOP18(__VA_ARGS__)
-#define RPC_CHOP20(__rc_a, __rc_b, ...) RPC_CHOP19(__VA_ARGS__)
-#define RPC_CHOP21(__rc_a, __rc_b, ...) RPC_CHOP20(__VA_ARGS__)
-#define RPC_CHOP22(__rc_a, __rc_b, ...) RPC_CHOP21(__VA_ARGS__)
-#define RPC_CHOP23(__rc_a, __rc_b, ...) RPC_CHOP22(__VA_ARGS__)
-#define RPC_CHOP24(__rc_a, __rc_b, ...) RPC_CHOP23(__VA_ARGS__)
-#define RPC_CHOP25(__rc_a, __rc_b, ...) RPC_CHOP24(__VA_ARGS__)
-#define RPC_CHOP_(__rc_count, ...) RPC_CHOP##__rc_count (__VA_ARGS__)
-#define RPC_CHOP(__rc_count, ...) RPC_CHOP_(__rc_count, __VA_ARGS__)
+#define RPC_CHOP2_0(...) __VA_ARGS__
+#define RPC_CHOP2_1(__rc_a, __rc_b, ...) RPC_CHOP2_0(__VA_ARGS__)
+#define RPC_CHOP2_2(__rc_a, __rc_b, ...) RPC_CHOP2_1(__VA_ARGS__)
+#define RPC_CHOP2_3(__rc_a, __rc_b, ...) RPC_CHOP2_2(__VA_ARGS__)
+#define RPC_CHOP2_4(__rc_a, __rc_b, ...) RPC_CHOP2_3(__VA_ARGS__)
+#define RPC_CHOP2_5(__rc_a, __rc_b, ...) RPC_CHOP2_4(__VA_ARGS__)
+#define RPC_CHOP2_6(__rc_a, __rc_b, ...) RPC_CHOP2_5(__VA_ARGS__)
+#define RPC_CHOP2_7(__rc_a, __rc_b, ...) RPC_CHOP2_6(__VA_ARGS__)
+#define RPC_CHOP2_8(__rc_a, __rc_b, ...) RPC_CHOP2_7(__VA_ARGS__)
+#define RPC_CHOP2_9(__rc_a, __rc_b, ...) RPC_CHOP2_8(__VA_ARGS__)
+#define RPC_CHOP2_10(__rc_a, __rc_b, ...) RPC_CHOP2_9(__VA_ARGS__)
+#define RPC_CHOP2_11(__rc_a, __rc_b, ...) RPC_CHOP2_10(__VA_ARGS__)
+#define RPC_CHOP2_12(__rc_a, __rc_b, ...) RPC_CHOP2_11(__VA_ARGS__)
+#define RPC_CHOP2_13(__rc_a, __rc_b, ...) RPC_CHOP2_12(__VA_ARGS__)
+#define RPC_CHOP2_14(__rc_a, __rc_b, ...) RPC_CHOP2_13(__VA_ARGS__)
+#define RPC_CHOP2_15(__rc_a, __rc_b, ...) RPC_CHOP2_14(__VA_ARGS__)
+#define RPC_CHOP2_16(__rc_a, __rc_b, ...) RPC_CHOP2_15(__VA_ARGS__)
+#define RPC_CHOP2_17(__rc_a, __rc_b, ...) RPC_CHOP2_16(__VA_ARGS__)
+#define RPC_CHOP2_18(__rc_a, __rc_b, ...) RPC_CHOP2_17(__VA_ARGS__)
+#define RPC_CHOP2_19(__rc_a, __rc_b, ...) RPC_CHOP2_18(__VA_ARGS__)
+#define RPC_CHOP2_20(__rc_a, __rc_b, ...) RPC_CHOP2_19(__VA_ARGS__)
+#define RPC_CHOP2_21(__rc_a, __rc_b, ...) RPC_CHOP2_20(__VA_ARGS__)
+#define RPC_CHOP2_22(__rc_a, __rc_b, ...) RPC_CHOP2_21(__VA_ARGS__)
+#define RPC_CHOP2_23(__rc_a, __rc_b, ...) RPC_CHOP2_22(__VA_ARGS__)
+#define RPC_CHOP2_24(__rc_a, __rc_b, ...) RPC_CHOP2_23(__VA_ARGS__)
+#define RPC_CHOP2_25(__rc_a, __rc_b, ...) RPC_CHOP2_24(__VA_ARGS__)
+#define RPC_CHOP2_(__rc_count, ...) RPC_CHOP2_##__rc_count (__VA_ARGS__)
+#define RPC_CHOP2(__rc_count, ...) RPC_CHOP2_(__rc_count, __VA_ARGS__)
/* Given a list of arguments, returns the first COUNT **pairs** of
arguments, the elements of each pair separated by SEP and each pair
@@ -576,182 +650,405 @@
#define RPC_GRAB_(__rg_count, ...) RPC_GRAB_##__rg_count (__VA_ARGS__)
#define RPC_GRAB(__rg_count, ...) RPC_GRAB_(__rg_count, __VA_ARGS__)
+#define RPC_TYPE_SHIFT_0(...)
+#define RPC_TYPE_SHIFT_1(__ra_new_type, __ra_type, __ra_arg, ...) __ra_new_type, __ra_arg RPC_TYPE_SHIFT_0(__ra_new_type, __VA_ARGS__)
+#define RPC_TYPE_SHIFT_2(__ra_new_type, __ra_type, __ra_arg, ...) __ra_new_type, __ra_arg, RPC_TYPE_SHIFT_1(__ra_new_type, __VA_ARGS__)
+#define RPC_TYPE_SHIFT_3(__ra_new_type, __ra_type, __ra_arg, ...) __ra_new_type, __ra_arg, RPC_TYPE_SHIFT_2(__ra_new_type, __VA_ARGS__)
+#define RPC_TYPE_SHIFT_4(__ra_new_type, __ra_type, __ra_arg, ...) __ra_new_type, __ra_arg, RPC_TYPE_SHIFT_3(__ra_new_type, __VA_ARGS__)
+#define RPC_TYPE_SHIFT_5(__ra_new_type, __ra_type, __ra_arg, ...) __ra_new_type, __ra_arg, RPC_TYPE_SHIFT_4(__ra_new_type, __VA_ARGS__)
+#define RPC_TYPE_SHIFT_6(__ra_new_type, __ra_type, __ra_arg, ...) __ra_new_type, __ra_arg, RPC_TYPE_SHIFT_5(__ra_new_type, __VA_ARGS__)
+#define RPC_TYPE_SHIFT_7(__ra_new_type, __ra_type, __ra_arg, ...) __ra_new_type, __ra_arg, RPC_TYPE_SHIFT_6(__ra_new_type, __VA_ARGS__)
+#define RPC_TYPE_SHIFT_8(__ra_new_type, __ra_type, __ra_arg, ...) __ra_new_type, __ra_arg, RPC_TYPE_SHIFT_7(__ra_new_type, __VA_ARGS__)
+#define RPC_TYPE_SHIFT_9(__ra_new_type, __ra_type, __ra_arg, ...) __ra_new_type, __ra_arg, RPC_TYPE_SHIFT_8(__ra_new_type, __VA_ARGS__)
+#define RPC_TYPE_SHIFT_10(__ra_new_type, __ra_type, __ra_arg, ...) __ra_new_type, __ra_arg, RPC_TYPE_SHIFT_9(__ra_new_type, __VA_ARGS__)
+#define RPC_TYPE_SHIFT_11(__ra_new_type, __ra_type, __ra_arg, ...) __ra_new_type, __ra_arg, RPC_TYPE_SHIFT_10(__ra_new_type, __VA_ARGS__)
+#define RPC_TYPE_SHIFT_12(__ra_new_type, __ra_type, __ra_arg, ...) __ra_new_type, __ra_arg, RPC_TYPE_SHIFT_11(__ra_new_type, __VA_ARGS__)
+#define RPC_TYPE_SHIFT_13(__ra_new_type, __ra_type, __ra_arg, ...) __ra_new_type, __ra_arg, RPC_TYPE_SHIFT_12(__ra_new_type, __VA_ARGS__)
+#define RPC_TYPE_SHIFT_14(__ra_new_type, __ra_type, __ra_arg, ...) __ra_new_type, __ra_arg, RPC_TYPE_SHIFT_13(__ra_new_type, __VA_ARGS__)
+#define RPC_TYPE_SHIFT_15(__ra_new_type, __ra_type, __ra_arg, ...) __ra_new_type, __ra_arg, RPC_TYPE_SHIFT_14(__ra_new_type, __VA_ARGS__)
+#define RPC_TYPE_SHIFT_16(__ra_new_type, __ra_type, __ra_arg, ...) __ra_new_type, __ra_arg, RPC_TYPE_SHIFT_15(__ra_new_type, __VA_ARGS__)
+#define RPC_TYPE_SHIFT_17(__ra_new_type, __ra_type, __ra_arg, ...) __ra_new_type, __ra_arg, RPC_TYPE_SHIFT_16(__ra_new_type, __VA_ARGS__)
+#define RPC_TYPE_SHIFT_18(__ra_new_type, __ra_type, __ra_arg, ...) __ra_new_type, __ra_arg, RPC_TYPE_SHIFT_17(__ra_new_type, __VA_ARGS__)
+#define RPC_TYPE_SHIFT_19(__ra_new_type, __ra_type, __ra_arg, ...) __ra_new_type, __ra_arg, RPC_TYPE_SHIFT_18(__ra_new_type, __VA_ARGS__)
+#define RPC_TYPE_SHIFT_20(__ra_new_type, __ra_type, __ra_arg, ...) __ra_new_type, __ra_arg, RPC_TYPE_SHIFT_19(__ra_new_type, __VA_ARGS__)
+#define RPC_TYPE_SHIFT_(__ra_count, __ra_new_type, ...) RPC_TYPE_SHIFT_##__ra_count(__ra_new_type, __VA_ARGS__)
+#ifdef RM_INTERN
+# define RPC_TYPE_SHIFT(__ra_count, __ra_new_type, ...) RPC_TYPE_SHIFT_(__ra_count, __ra_new_type, __VA_ARGS__)
+#else
+# define RPC_TYPE_SHIFT(__ra_count, __ra_new_type, ...) __VA_ARGS__
+#endif
+
/* Ensure that there are X pairs of arguments. */
#define RPC_INVALID_NUMBER_OF_ARGUMENTS_
#define RPC_EMPTY_LIST_(x) RPC_INVALID_NUMBER_OF_ARGUMENTS_##x
#define RPC_EMPTY_LIST(x) RPC_EMPTY_LIST_(x)
#define RPC_ENSURE_ARGS(count, ...) \
- RPC_EMPTY_LIST (RPC_CHOP (count, __VA_ARGS__))
-
-#define RPC_MARSHAL_GEN_(id, icount, ocount, ...) \
- RPC_ENSURE_ARGS(CPP_ADD (icount, ocount), ##__VA_ARGS__) \
+ RPC_EMPTY_LIST (RPC_CHOP2 (count, __VA_ARGS__))
+
+#define RPC_SEND_MARSHAL_GEN_(id, in_count, out_count, ret_cap_count, ...) \
+ RPC_SEND_MARSHAL(id, in_count, ##__VA_ARGS__) \
+ RPC_SEND_UNMARSHAL(id, in_count, ##__VA_ARGS__)
+
+#define RPC_RECEIVE_MARSHAL_GEN_(id, in_count, out_count, ret_cap_count, ...) \
+ RPC_RECEIVE_MARSHAL(id, ret_cap_count, \
+ RPC_CHOP2 (CPP_ADD (in_count, out_count), \
+ ##__VA_ARGS__))
+
+#define RPC_REPLY_MARSHAL_GEN_(id, in_count, out_count, ret_cap_count, ...) \
+ RPC_REPLY_MARSHAL(id, out_count, ret_cap_count, \
+ RPC_CHOP2 (in_count, ##__VA_ARGS__)) \
+ RPC_REPLY_UNMARSHAL(id, out_count, ret_cap_count, \
+ RPC_CHOP2 (in_count, ##__VA_ARGS__))
+
+#define RPC_MARSHAL_GEN_(id, in_count, out_count, ret_cap_count, ...) \
+ RPC_ENSURE_ARGS(CPP_ADD (CPP_ADD (in_count, out_count), \
+ ret_cap_count), \
+ ##__VA_ARGS__) \
+ RPC_SEND_MARSHAL_GEN_(id, in_count, out_count, ret_cap_count, \
+ ##__VA_ARGS__) \
+ RPC_RECEIVE_MARSHAL_GEN_(id, in_count, out_count, ret_cap_count, \
+ ##__VA_ARGS__) \
+ RPC_REPLY_MARSHAL_GEN_(id, in_count, out_count, ret_cap_count, \
+ ##__VA_ARGS__)
+
+/* Send a message. __RPC_REPY_MESSENGER designates the messenger that
+ should receive the reply. (Its buffer should have already been
+ prepared using, e.g., the corresponding receive_marshal
+ function.) */
+#ifndef RM_INTERN
+#define RPC_SEND_(postfix, id, in_count, out_count, ret_cap_count, ...) \
+ static inline error_t \
+ __attribute__((always_inline)) \
+ RPC_CONCAT(RPC_STUB_PREFIX_(id), postfix) \
+ (cap_t __rpc_activity, cap_t __rpc_object \
+ RPC_IF_COMMA (in_count) () \
+ RPC_GRAB2 (, in_count, __VA_ARGS__), \
+ cap_t __rpc_reply_messenger) \
+ { \
+ struct hurd_message_buffer *mb = hurd_message_buffer_alloc (); \
+ mb->just_free = true; \
\
- RPC_SEND_MARSHAL(id, icount, ##__VA_ARGS__) \
- RPC_SEND_UNMARSHAL(id, icount, ##__VA_ARGS__) \
- RPC_REPLY_MARSHAL(id, ocount, RPC_CHOP (icount, ##__VA_ARGS__)) \
- RPC_REPLY_UNMARSHAL(id, ocount, RPC_CHOP (icount, ##__VA_ARGS__))
+ RPC_CONCAT (RPC_STUB_PREFIX_(id), _send_marshal) \
+ (mb->request \
+ RPC_IF_COMMA (in_count) () RPC_ARGUMENTS(in_count,, __VA_ARGS__), \
+ __rpc_reply_messenger); \
+ \
+ error_t err = vg_send (VG_IPC_SEND_SET_THREAD_TO_CALLER \
+ | VG_IPC_SEND_SET_ASROOT_TO_CALLERS, \
+ __rpc_activity, __rpc_object, \
+ mb->sender, ADDR_VOID); \
+ \
+ return err; \
+ }
+#else
+#define RPC_SEND_(postfix, id, in_count, out_count, ret_cap_count, ...)
+#endif
-#define RPC_SIMPLE_(postfix, id, icount, ocount, ...) \
- /* Send, but do not wait for a reply. */ \
+/* Send a message. Abort if the target is not ready. */
+#ifndef RM_INTERN
+#define RPC_SEND_NONBLOCKING_(postfix, id, in_count, out_count, ret_cap_count, ...) \
static inline error_t \
__attribute__((always_inline)) \
RPC_CONCAT(RPC_STUB_PREFIX_(id), postfix) \
- (RPC_TARGET_ARG_ RPC_GRAB2 (, icount, __VA_ARGS__)) \
+ (cap_t __rpc_activity, cap_t __rpc_object \
+ RPC_IF_COMMA (in_count) () \
+ RPC_GRAB2 (, in_count, __VA_ARGS__), \
+ cap_t __rpc_reply_messenger) \
{ \
- l4_msg_tag_t tag; \
- l4_msg_t msg; \
+ struct hurd_message_buffer *mb = hurd_message_buffer_alloc (); \
\
RPC_CONCAT (RPC_STUB_PREFIX_(id), _send_marshal) \
- CPP_IFTHEN (icount, \
- (&msg, RPC_ARGUMENTS(icount, __VA_ARGS__)), \
- (&msg)); \
+ (mb->request \
+ RPC_IF_COMMA (in_count) () RPC_ARGUMENTS(in_count,, __VA_ARGS__), \
+ __rpc_reply_messenger); \
\
- l4_msg_load (msg); \
- l4_accept (L4_UNTYPED_WORDS_ACCEPTOR); \
+ error_t err = vg_reply (VG_IPC_SEND_SET_THREAD_TO_CALLER \
+ | VG_IPC_SEND_SET_ASROOT_TO_CALLERS, \
+ __rpc_activity, __rpc_object, \
+ mb->sender, ADDR_VOID); \
\
- for (;;) \
- { \
- tag = l4_send (RPC_TARGET_); \
- if (unlikely (l4_ipc_failed (tag))) \
- { \
- if (((l4_error_code () >> 1) & 0x7) == 3) \
- /* IPC was interrupted. */ \
- /* XXX: We need to somehow consider the signal state and \
- return EINTR if appropriate. */ \
- continue; \
- return EHOSTDOWN; \
- } \
- break; \
- } \
+ hurd_message_buffer_free (mb); \
\
- return 0; \
+ return err; \
}
+#else
+#define RPC_SEND_NONBLOCKING_(postfix, id, in_count, out_count, ret_cap_count, ...)
+#endif
-#define RPC_(postfix, id, icount, ocount, ...) \
+/* Send a message and wait for a reply. */
+#ifndef RM_INTERN
+#define RPC_(postfix, id, in_count, out_count, ret_cap_count, ...) \
static inline error_t \
__attribute__((always_inline)) \
- RPC_CONCAT (RPC_STUB_PREFIX_(id), postfix) \
- (RPC_TARGET_ARG_ \
- RPC_GRAB (CPP_ADD(icount, ocount), \
- RPC_GRAB2 (, icount, __VA_ARGS__) RPC_IF_COMMA(icount) () \
- RPC_GRAB2 (*, ocount, RPC_CHOP (icount, __VA_ARGS__)))) \
+ RPC_CONCAT (RPC_CONCAT (RPC_STUB_PREFIX_(id), _using), postfix) \
+ (struct hurd_message_buffer *mb, \
+ addr_t __rpc_activity, \
+ addr_t __rpc_object \
+ /* In arguments. */ \
+ RPC_IF_COMMA (in_count) () \
+ RPC_GRAB2 (, in_count, __VA_ARGS__) \
+ /* Out arguments (data and caps). */ \
+ RPC_IF_COMMA (CPP_ADD (out_count, ret_cap_count)) () \
+ RPC_GRAB2 (*, CPP_ADD (out_count, ret_cap_count), \
+ RPC_CHOP2 (in_count, __VA_ARGS__))) \
{ \
- l4_msg_tag_t tag; \
- l4_msg_t msg; \
+ /* Prepare the reply buffer. */ \
+ RPC_CONCAT (RPC_STUB_PREFIX_(id), _receive_marshal) \
+ (mb->reply \
+ RPC_IF_COMMA (ret_cap_count) () \
+ CPP_FOREACH(ret_cap_count, CPP_SAFE_DEREF, ADDR_VOID, \
+ RPC_ARGUMENTS (ret_cap_count, , \
+ RPC_CHOP2 (CPP_ADD (in_count, out_count), \
+ __VA_ARGS__)))); \
\
+ /* Then the send buffer. */ \
RPC_CONCAT (RPC_STUB_PREFIX_(id), _send_marshal) \
- CPP_IFTHEN (icount, \
- (&msg, RPC_ARGUMENTS(icount, __VA_ARGS__)), \
- (&msg)); \
+ (mb->request \
+ RPC_IF_COMMA (in_count) () \
+ RPC_ARGUMENTS (in_count,, __VA_ARGS__), \
+ mb->receiver); \
\
- l4_msg_load (msg); \
- l4_accept (l4_map_grant_items (L4_COMPLETE_ADDRESS_SPACE)); \
+ hurd_activation_message_register (mb); \
\
- bool call = true; \
- for (;;) \
- { \
- if (call) \
- tag = l4_call (RPC_TARGET_); \
- else \
- tag = l4_receive (RPC_TARGET_); \
- if (unlikely (l4_ipc_failed (tag))) \
- { \
- if (((l4_error_code () >> 1) & 0x7) == 3) \
- /* IPC was interrupted. */ \
- /* XXX: We need to somehow consider the signal state and \
- return EINTR if appropriate. */ \
- { \
- if ((l4_error_code () & 1)) \
- /* Error occurred during receive phase. */ \
- call = false; \
+ /* We will be resumed via an activation. */ \
+ error_t err = vg_ipc (VG_IPC_RECEIVE | VG_IPC_SEND \
+ | VG_IPC_RECEIVE_ACTIVATE \
+ | VG_IPC_SEND_SET_THREAD_TO_CALLER \
+ | VG_IPC_SEND_SET_ASROOT_TO_CALLERS \
+ | VG_IPC_RECEIVE_SET_THREAD_TO_CALLER \
+ | VG_IPC_RECEIVE_SET_ASROOT_TO_CALLERS, \
+ __rpc_activity, \
+ mb->receiver_strong, ADDR_VOID, \
+ __rpc_activity, __rpc_object, \
+ mb->sender, ADDR_VOID); \
+ if (err) \
+ /* Error sending the IPC. */ \
+ hurd_activation_message_unregister (mb); \
+ else \
+ err = RPC_CONCAT (RPC_STUB_PREFIX_(id), _reply_unmarshal) \
+ (mb->reply \
+ RPC_IF_COMMA (CPP_ADD (out_count, ret_cap_count)) () \
+ RPC_ARGUMENTS (CPP_ADD (out_count, ret_cap_count),, \
+ RPC_CHOP2 (in_count, ##__VA_ARGS__))); \
\
- continue; \
- } \
- return EHOSTDOWN; \
- } \
- break; \
- } \
- \
- l4_msg_store (tag, msg); \
- return RPC_CONCAT (RPC_STUB_PREFIX_(id), _reply_unmarshal) \
- CPP_IFTHEN (ocount, \
- (&msg, RPC_ARGUMENTS (ocount, \
- RPC_CHOP (icount, ##__VA_ARGS__))), \
- (&msg)); \
+ return err; \
} \
+ \
+ static inline error_t \
+ __attribute__((always_inline)) \
+ RPC_CONCAT (RPC_STUB_PREFIX_(id), postfix) \
+ (addr_t __rpc_activity, \
+ addr_t __rpc_object \
+ /* In arguments. */ \
+ RPC_IF_COMMA (in_count) () \
+ RPC_GRAB2 (, in_count, __VA_ARGS__) \
+ /* Out arguments (data and caps). */ \
+ RPC_IF_COMMA (CPP_ADD (out_count, ret_cap_count)) () \
+ RPC_GRAB2 (*, CPP_ADD (out_count, ret_cap_count), \
+ RPC_CHOP2 (in_count, __VA_ARGS__))) \
+ { \
+ struct hurd_message_buffer *mb = hurd_message_buffer_alloc (); \
+ \
+ error_t err; \
+ err = RPC_CONCAT (RPC_CONCAT (RPC_STUB_PREFIX_(id), _using), postfix) \
+ (mb, __rpc_activity, __rpc_object \
+ RPC_IF_COMMA (CPP_ADD (CPP_ADD (in_count, out_count), \
+ ret_cap_count)) () \
+ RPC_ARGUMENTS (CPP_ADD (CPP_ADD (in_count, out_count), \
+ ret_cap_count),, __VA_ARGS__)); \
+ \
+ hurd_message_buffer_free (mb); \
+ \
+ return err; \
+ }
+#else
+# define RPC_(postfix, id, in_count, out_count, ret_cap_count, ...)
+#endif
-/* Generate stubs for marshalling a reply and sending it (without
- blocking). */
-#define RPC_REPLY_(id, icount, ocount, ...) \
+/* Send a reply to __RPC_TARGET. If __RPC_TARGET does not accept the
+ message immediately, abort sending. */
+#ifndef RM_INTERN
+#define RPC_REPLY_(id, in_count, out_count, ret_cap_count, ...) \
static inline error_t \
RPC_CONCAT (RPC_STUB_PREFIX_(id), _reply) \
- (l4_thread_id_t tid RPC_IF_COMMA (ocount) () \
- RPC_GRAB2 (, ocount, RPC_CHOP (icount, ##__VA_ARGS__))) \
+ (addr_t __rpc_activity, \
+ addr_t __rpc_target \
+ /* Out data. */ \
+ RPC_IF_COMMA (out_count) () \
+ RPC_GRAB2 (, out_count, RPC_CHOP2 (in_count, ##__VA_ARGS__)) \
+ /* Return capabilities. */ \
+ RPC_IF_COMMA (ret_cap_count) () \
+ RPC_GRAB2 (, ret_cap_count, \
+ RPC_CHOP2 (CPP_ADD (in_count, out_count), \
+ ##__VA_ARGS__))) \
{ \
- l4_msg_tag_t tag; \
- l4_msg_t msg; \
+ struct hurd_message_buffer *mb = hurd_message_buffer_alloc (); \
\
RPC_CONCAT (RPC_STUB_PREFIX_(id), _reply_marshal) \
- (&msg RPC_IF_COMMA (ocount) () \
- RPC_ARGUMENTS(ocount, RPC_CHOP (icount, __VA_ARGS__))); \
+ (mb->request \
+ /* Out data. */ \
+ RPC_IF_COMMA (out_count) () \
+ RPC_ARGUMENTS(out_count,, RPC_CHOP2 (in_count, __VA_ARGS__)) \
+ /* Out capabilities. */ \
+ RPC_IF_COMMA (ret_cap_count) () \
+ RPC_ARGUMENTS(ret_cap_count,, \
+ RPC_CHOP2 (CPP_ADD (in_count, out_count), \
+ __VA_ARGS__))); \
\
- l4_msg_load (msg); \
- l4_accept (L4_UNTYPED_WORDS_ACCEPTOR); \
+ error_t err = vg_reply (VG_IPC_SEND_SET_THREAD_TO_CALLER \
+ | VG_IPC_SEND_SET_ASROOT_TO_CALLERS, \
+ __rpc_activity, __rpc_target, \
+ mb->sender, ADDR_VOID); \
\
- tag = l4_reply (tid); \
- if (l4_ipc_failed (tag)) \
- return EHOSTDOWN; \
- return 0; \
+ hurd_message_buffer_free (mb); \
+ \
+ return err; \
}
+#else
+#define RPC_REPLY_(id, in_count, out_count, ret_cap_count, ...) \
+ static inline error_t \
+ __attribute__((always_inline)) \
+ RPC_CONCAT (RPC_STUB_PREFIX_(id), _reply) \
+ (struct activity *__rpc_activity, \
+ struct messenger *__rpc_target \
+ /* Out data. */ \
+ RPC_IF_COMMA (out_count) () \
+ RPC_GRAB2 (, out_count, RPC_CHOP2 (in_count, ##__VA_ARGS__)) \
+ /* Return capabilities. */ \
+ RPC_IF_COMMA (ret_cap_count) () \
+ RPC_GRAB2 (, ret_cap_count, \
+ RPC_TYPE_SHIFT (ret_cap_count, struct cap, \
+ RPC_CHOP2 (CPP_ADD (in_count, out_count), \
+ ##__VA_ARGS__)))) \
+ { \
+ RPC_CONCAT (RPC_STUB_PREFIX_(id), _reply_marshal) \
+ (reply_buffer \
+ /* Out data. */ \
+ RPC_IF_COMMA (out_count) () \
+ RPC_ARGUMENTS(out_count,, RPC_CHOP2 (in_count, ##__VA_ARGS__)) \
+ /* Out capabilities. */ \
+ RPC_IF_COMMA (ret_cap_count) () \
+ RPC_ARGUMENTS (ret_cap_count, &, \
+ RPC_CHOP2 (CPP_ADD (in_count, out_count), \
+ ##__VA_ARGS__))); \
+ \
+ bool ret = messenger_message_load (__rpc_activity, \
+ __rpc_target, reply_buffer); \
+ \
+ return ret ? 0 : EWOULDBLOCK; \
+ }
+#endif
+
+/* RPC template. ID is the method name. IN_COUNT is the number of
+ arguments. OUT_COUNT is the number of out arguments.
+ RET_CAP_COUNT is the number of capabilities that are returned. The
+ remaining arguments correspond to pairs of types and argument
+ names.
+
+ Consider:
+
+ RPC(method, 2, 1, 1,
+ // In (data and capability) parameters
+ int, foo, cap_t, bar,
+ // Out data parameters
+ int bam,
+ // Out capabilities
+ cap_t xyzzy)
+
+ This will generate marshalling and unmarshalling functions as well
+ as send, reply and call functions. For instance, the signature for
+ the correspond send marshal function is:
+
+ error_t method_send_marshal (struct vg_message *message,
+ int foo, cap_t bar, cap_t reply)
+
+ that of the send unmarshal function is:
+
+ error_t method_send_unmarshal (struct vg_message *message,
+ int *foo, cap_t *bar, cap_t *reply)
+
+ that of the receive marshal function is:
+
+ error_t method_receive_marshal (struct vg_message *message,
+ cap_t xyzzy)
+
+
+ that of the reply marshal function is:
+
+ error_t method_reply_marshal (struct vg_message *message,
+ int bam, cap_t xyzzy)
-/* RPC template. ID is the method name, ARGS is the list of arguments
- as normally passed to a function, LOADER is code to load the in
- parameters, and STORER is code to load the out parameters. The
- code assumes that the first MR contains the error code and returns
- this as the function return value. If the IPC fails, EHOSTDOWN is
- returned. */
-
-#define RPC_SIMPLE(id, icount, ocount, ...) \
- RPC_MARSHAL_GEN_(id, icount, ocount, ##__VA_ARGS__) \
- \
- RPC_SIMPLE_(, id, icount, ocount, ##__VA_ARGS__) \
- RPC_SIMPLE_(_send, id, icount, ocount, ##__VA_ARGS__) \
- RPC_(_call, id, icount, ocount, ##__VA_ARGS__) \
- \
- RPC_REPLY_(id, icount, ocount, ##__VA_ARGS__)
-
-#define RPC(id, icount, ocount, ...) \
- RPC_MARSHAL_GEN_(id, icount, ocount, ##__VA_ARGS__) \
- \
- RPC_(, id, icount, ocount, ##__VA_ARGS__) \
- RPC_SIMPLE_(_send, id, icount, ocount, ##__VA_ARGS__) \
- RPC_(_call, id, icount, ocount, ##__VA_ARGS__) \
- \
- RPC_REPLY_(id, icount, ocount, ##__VA_ARGS__)
+ that of the reply unmarshal function is:
+
+ error_t method_reply_unmarshal (struct vg_message *message,
+ int *bam, cap_t *xyzzy)
+
+ Functions to send requests and replies as well as to produce calls
+ are also generated.
+
+ error_t method_call (cap_t activity, cap_t object,
+ int foo, cap_t bar, int *bam, cap_t *xyzzy)
+
+ Note that *XYZZY must be initialize with the location of a
+ capability slot to store the returned capability. *XYZZY is set to
+ ADDR_VOID if the sender did not provide a capability.
+
+ To send a message and not wait for a reply, a function with the
+ following prototype is generated:
+
+ error_t method_send (cap_t activity, cap_t object,
+ int foo, cap_t bar,
+ cap_t reply_messenger)
+
+ To reply to a request, a function with the following prototype is
+ generated:
+
+ error_t method_reply (cap_t activity, cap_t reply_messenger,
+ int bam, cap_t xyzzy)
+*/
+
+#define RPC(id, in_count, out_count, ret_cap_count, ...) \
+ RPC_MARSHAL_GEN_(id, in_count, out_count, ret_cap_count, ##__VA_ARGS__) \
+ \
+ RPC_(, id, in_count, out_count, ret_cap_count, ##__VA_ARGS__) \
+ RPC_SEND_(_send, id, in_count, out_count, ret_cap_count, \
+ ##__VA_ARGS__) \
+ RPC_SEND_NONBLOCKING_(_send_nonblocking, \
+ id, in_count, out_count, ret_cap_count, \
+ ##__VA_ARGS__) \
+ RPC_REPLY_(id, in_count, out_count, ret_cap_count, ##__VA_ARGS__)
/* Marshal a reply consisting of the error code ERR in *MSG. */
static inline void
-rpc_error_reply_marshal (l4_msg_t *msg, error_t err)
+__attribute__((always_inline))
+rpc_error_reply_marshal (struct vg_message *msg, error_t err)
{
- l4_msg_clear (*msg);
- l4_msg_put_word (*msg, 0, err);
- l4_msg_set_untyped_words (*msg, 1);
+ vg_message_clear (msg);
+ vg_message_append_word (msg, err);
}
-/* Reply to the thread THREAD with error code ERROR. */
+/* Reply to the target TARGET with error code ERROR. */
+#ifdef RM_INTERN
static inline error_t
-rpc_error_reply (l4_thread_id_t thread, error_t err)
+__attribute__((always_inline))
+rpc_error_reply (struct activity *activity, struct messenger *target,
+ error_t err)
{
- l4_msg_t msg;
-
- rpc_error_reply_marshal (&msg, err);
- l4_msg_load (msg);
-
- l4_msg_tag_t tag;
- tag = l4_reply (thread);
- if (l4_ipc_failed (tag))
- return EHOSTDOWN;
- return 0;
+ rpc_error_reply_marshal (reply_buffer, err);
+ bool ret = messenger_message_load (activity, target, reply_buffer);
+ return ret ? 0 : EWOULDBLOCK;
}
+#else
+static inline error_t
+__attribute__((always_inline))
+rpc_error_reply (cap_t activity, cap_t target, error_t err)
+{
+ return vg_ipc_short (VG_IPC_SEND_NONBLOCKING | VG_IPC_SEND_INLINE
+ | VG_IPC_SEND_INLINE_WORD1,
+ ADDR_VOID, ADDR_VOID, ADDR_VOID,
+ ADDR_VOID, target,
+ ADDR_VOID, err, 0, ADDR_VOID);
+}
+#endif
#endif