/ duct-tape / include / darlingserver / duct-tape.h
duct-tape.h
  1  #ifndef _DARLINGSERVER_DUCT_TAPE_H_
  2  #define _DARLINGSERVER_DUCT_TAPE_H_
  3  
  4  #include <stdint.h>
  5  #include <stddef.h>
  6  #include <stdbool.h>
  7  
  8  #include <libsimple/lock.h>
  9  #include <darlingserver/rpc.internal.h>
 10  #include <darlingserver/rpc-supplement.h>
 11  #include <darlingserver/rpc.h>
 12  
 13  #include <darlingserver/duct-tape/types.h>
 14  #include <darlingserver/duct-tape/hooks.h>
 15  
 16  #ifdef __cplusplus
 17  extern "C" {
 18  #endif
 19  
 20  void dtape_init(const dtape_hooks_t* hooks);
 21  void dtape_init_in_thread(void);
 22  void dtape_deinit(void);
 23  
 24  uint32_t dtape_task_self_trap(void);
 25  uint32_t dtape_host_self_trap(void);
 26  uint32_t dtape_thread_self_trap(void);
 27  uint32_t dtape_mach_reply_port(void);
 28  uint32_t dtape_thread_get_special_reply_port(void);
 29  uint32_t dtape_mk_timer_create(void);
 30  
 31  DSERVER_DTAPE_DECLS;
 32  
 33  typedef void (*dtape_kqchan_mach_port_notification_callback_f)(void* context);
 34  
 35  /**
 36   * The threshold beyond which thread IDs are considered IDs for kernel threads.
 37   * Thread IDs lower than this value are reserved for userspace threads.
 38   * Thread IDs greater than or equal to this value are reserved for kernelspace threads.
 39   *
 40   * This should NOT be used to differentiate kernelspace threads from userspace ones.
 41   * This is simply used as a convenient cutoff beyond which we do not expect Linux to actually assign
 42   * thread IDs within our namespace. In practice, there should be no difference between the way userspace
 43   * and kernelspace threads are handled in the duct-tape code.
 44   *
 45   * This is used as the starting offset for thread IDs for kernelspace threads (which do not have a "real" managed Darling thread backing them).
 46   */
 47  #define DTAPE_KERNEL_THREAD_ID_THRESHOLD (1ULL << 22)
 48  
 49  /**
 50   * Creates a new duct-tape task. The caller receives a reference on the new task.
 51   *
 52   * An @p nsid value of `0` indicates the task being created is the kernel task.
 53   */
 54  dtape_task_t* dtape_task_create(dtape_task_t* parent_task, uint32_t nsid, void* context, dserver_rpc_architecture_t architecture);
 55  dtape_thread_t* dtape_thread_create(dtape_task_t* task, uint64_t nsid, void* context);
 56  dtape_kqchan_mach_port_t* dtape_kqchan_mach_port_create(dtape_task_t* owning_task, uint32_t port, uint64_t receive_buffer, uint64_t receive_buffer_size, uint64_t saved_filter_flags, dtape_kqchan_mach_port_notification_callback_f notification_callback, void* context);
 57  dtape_semaphore_t* dtape_semaphore_create(dtape_task_t* owning_task, int initial_value);
 58  
 59  void dtape_kqchan_mach_port_destroy(dtape_kqchan_mach_port_t* kqchan);
 60  void dtape_semaphore_destroy(dtape_semaphore_t* semaphore);
 61  
 62  void dtape_thread_entering(dtape_thread_t* thread);
 63  void dtape_thread_exiting(dtape_thread_t* thread);
 64  void dtape_thread_set_handles(dtape_thread_t* thread, uintptr_t pthread_handle, uintptr_t dispatch_qaddr);
 65  /**
 66   * Returns the thread corresponding to the given thread port.
 67   *
 68   * @warning It is VERY important that the caller ensures the thread cannot die while we're looking it up.
 69   *          This can be accomplished, for example, by locking the global thread list before the call.
 70   */
 71  dtape_thread_t* dtape_thread_for_port(uint32_t thread_port);
 72  void* dtape_thread_context(dtape_thread_t* thread);
 73  int dtape_thread_load_state_from_user(dtape_thread_t* thread, uintptr_t thread_state_address, uintptr_t float_state_address);
 74  int dtape_thread_save_state_to_user(dtape_thread_t* thread, uintptr_t thread_state_address, uintptr_t float_state_address);
 75  void dtape_thread_process_signal(dtape_thread_t* thread, int bsd_signal_number, int linux_signal_number, int code, uintptr_t signal_address);
 76  void dtape_thread_wait_while_user_suspended(dtape_thread_t* thread);
 77  void dtape_thread_retain(dtape_thread_t* thread);
 78  void dtape_thread_release(dtape_thread_t* thread);
 79  void dtape_thread_sigexc_enter(dtape_thread_t* thread);
 80  void dtape_thread_sigexc_exit(dtape_thread_t* thread);
 81  void dtape_thread_sigexc_enter2(dtape_thread_t* thread);
 82  void dtape_thread_dying(dtape_thread_t* thread);
 83  
 84  void dtape_task_uidgid(dtape_task_t* task, int new_uid, int new_gid, int* old_uid, int* old_gid);
 85  void dtape_task_retain(dtape_task_t* task);
 86  void dtape_task_release(dtape_task_t* task);
 87  void dtape_task_dying(dtape_task_t* task);
 88  void dtape_task_set_dyld_info(dtape_task_t* task, uint64_t address, uint64_t length);
 89  void dtape_task_set_sigexc_enabled(dtape_task_t* task, bool enabled);
 90  bool dtape_task_try_resume(dtape_task_t* task);
 91  
 92  /**
 93   * Invoked when a timer armed by an earlier call to the timer_arm hook expires.
 94   *
 95   * It is allowed to be invoked spuriously.
 96   */
 97  void dtape_timer_fired(void);
 98  
 99  void dtape_kqchan_mach_port_modify(dtape_kqchan_mach_port_t* kqchan, uint64_t receive_buffer, uint64_t receive_buffer_size, uint64_t saved_filter_flags);
100  void dtape_kqchan_mach_port_disable_notifications(dtape_kqchan_mach_port_t* kqchan);
101  bool dtape_kqchan_mach_port_fill(dtape_kqchan_mach_port_t* kqchan, dserver_kqchan_reply_mach_port_read_t* reply, uint64_t default_buffer, uint64_t default_buffer_size);
102  bool dtape_kqchan_mach_port_has_events(dtape_kqchan_mach_port_t* kqchan);
103  
104  void dtape_semaphore_up(dtape_semaphore_t* semaphore);
105  dtape_semaphore_wait_result_t dtape_semaphore_down(dtape_semaphore_t* semaphore);
106  bool dtape_semaphore_down_simple(dtape_semaphore_t* semaphore);
107  
108  uint64_t dtape_debug_task_port_count(dtape_task_t* task);
109  uint64_t dtape_debug_task_list_ports(dtape_task_t* task, dtape_debug_task_list_ports_iterator_f iterator, void* context);
110  uint64_t dtape_debug_portset_list_members(dtape_task_t* task, uint32_t portset, dtape_debug_portset_list_members_iterator_f iterator, void* context);
111  uint64_t dtape_debug_port_list_messages(dtape_task_t* task, uint32_t port, dtape_debug_port_list_messages_iterator_f iterator, void* context);
112  
113  #ifdef __cplusplus
114  };
115  #endif
116  
117  #endif // _DARLINGSERVER_DUCT_TAPE_H_