1 #ifndef SCHEME_FUTURES_H 2 #define SCHEME_FUTURES_H 3 4 #ifdef MZ_USE_FUTURES 5 6 typedef Scheme_Object* (*prim_obj_int_pobj_obj_t)(Scheme_Object*, int, Scheme_Object**); 7 typedef Scheme_Object* (*prim_int_pobj_obj_t)(int, Scheme_Object**); 8 typedef Scheme_Object* (*prim_int_pobj_obj_obj_t)(int, Scheme_Object**, Scheme_Object*); 9 typedef void* (*prim_pvoid_pvoid_pvoid_t)(void*, void*); 10 11 /* PENDING is ready to run: */ 12 #define PENDING 0 13 /* RUNNING is running in some thread: */ 14 #define RUNNING 1 15 /* WAITING_FOR_PRIM is waiting for the runtime thread to start runnin 16 a primitive -- possibiliy atomic, possibly not, and possibly a LWC 17 capture happens while waiting: */ 18 #define WAITING_FOR_PRIM 2 19 /* FINISHED means the result (or failure) is ready: */ 20 #define FINISHED 3 21 /* PENDING is ready to run, but won't work in a future thread: */ 22 #define PENDING_OVERSIZE 4 23 /* WAITING_FOR_PRIM is the runtime thread working on a primitive: */ 24 #define HANDLING_PRIM 5 25 /* WAITING_FOR_FSEMA is in the queue of an fsemaphore: */ 26 #define WAITING_FOR_FSEMA 6 27 /* SUSPENDED is the owning custodian is gone, so the future will never finish: */ 28 #define SUSPENDED 7 29 /* WAITING_FOR_OVERFLOW is waiting for an LCW capture to continue 30 for a stack overflow: */ 31 #define WAITING_FOR_OVERFLOW 8 32 33 /* FSRC_OTHER means: descriptive string is provided for logging, 34 called function *DOES NOT NEED* to lookup continuation marks. */ 35 #define FSRC_OTHER 0 36 /* FSRC_RATOR means: Racket function provided, so use it in logging, 37 called function can lookup continuation marks. */ 38 #define FSRC_RATOR 1 39 /* FSRC_PRIM means: Racket primitive provided, so use it in logging, 40 called function can lookup continuation marks. */ 41 #define FSRC_PRIM 2 42 /* FSRC_MARKS means: like FSRC_OTHER, but 43 called function may need to lookup continuation marks. */ 44 #define FSRC_MARKS 3 45 46 typedef struct Fevent { 47 double timestamp; 48 int what, fid, data; 49 } Fevent; 50 51 typedef struct Fevent_Buffer { 52 Fevent *a; 53 int pos, overflow; 54 int i, count; /* used during flush */ 55 } Fevent_Buffer; 56 57 typedef struct Scheme_Future_Thread_State { 58 int is_runtime_thread; 59 mz_proc_thread *t; 60 int id; 61 int worker_gc_counter; 62 mzrt_sema *worker_can_continue_sema; 63 intptr_t runstack_size; 64 65 /* After a future thread starts, only the runtime thread 66 modifies the values at these pointers. Future threads 67 read them without any locks; assembly-level instructions, 68 such as mfence, ensure that future threads eventually see 69 changes made by the runtime thread, and the runtime thread 70 waits as needed. */ 71 volatile int *fuel_pointer; 72 volatile uintptr_t *stack_boundary_pointer; 73 volatile int *need_gc_pointer; 74 75 Scheme_Thread *thread; 76 77 uintptr_t gen0_start; 78 uintptr_t gen0_size; 79 uintptr_t gen0_initial_offset; 80 81 int local_capture_failed; 82 83 int use_fevents1; 84 Fevent_Buffer fevents1; 85 Fevent_Buffer fevents2; 86 } Scheme_Future_Thread_State; 87 88 typedef struct future_t { 89 Scheme_Object so; 90 91 int id; 92 int thread_short_id; 93 94 int status; 95 /* The status field is the main locking mechanism. It 96 should only be read and written when holding a lock 97 (and all associated fields for a status should be 98 set at the same time). */ 99 100 mzrt_sema *can_continue_sema; 101 /* this semcpahore is non_NULL when a future thread is blocked 102 while trying to run the future; th want_lw flag may be set in 103 that case */ 104 105 Scheme_Object *orig_lambda; 106 107 Scheme_Custodian *cust; /* an approximate custodian; don't use a future 108 thread if this custodian is shut down */ 109 110 /* Runtime call stuff */ 111 112 char want_lw; 113 /* flag to indicate waiting for lw capture; if this flag is set, 114 then the future thread currently running the future must be 115 blocked, and the runtime thread must not already be working on 116 behalf of the future; since a future thread is blocked on this 117 future, then can_continue_sema is normally set, but the runtime 118 thread sets can_continue_sema to NULL while trying to capture the 119 continuation --- in case anoter thread tries to let the original 120 future thread continue because it was blocked on a touch for a 121 future that completed; the `want_lw' flag should be changed only 122 while holding a lock */ 123 124 char in_queue_waiting_for_lwc; 125 /* flag to indicate whether the future is in the "waiting for lwc" 126 queue; the future might be in the queue even if want_lw is set to 127 0, and so this flag just prevents */ 128 129 char in_touch_queue; 130 /* like `in_queue_waiting_for_lwc' but for being in a `touch' 131 future */ 132 133 char in_future_specific_touch_queue; /* a back-door argument */ 134 135 char rt_prim_is_atomic; 136 /* when a future thread is blocked on this future, it sets 137 `rt_prim_is_atomic' if the blocking operation can run 138 in any thread atomically (i.e., it's a "synchronizing" 139 operation insteda of a general blocking operation) */ 140 141 char in_future_queue, in_atomic_queue; 142 143 double time_of_request; 144 const char *source_of_request; 145 int source_type; 146 147 uintptr_t alloc_retval; 148 uintptr_t alloc_sz_retval; 149 int alloc_retval_counter; 150 151 void *prim_func; 152 int prim_protocol; 153 Scheme_Object *arg_s0; 154 const Scheme_Object *arg_t0; 155 Scheme_Object **arg_S0; 156 Scheme_Bucket *arg_b0; 157 int arg_i0; 158 intptr_t arg_l0; 159 size_t arg_z0; 160 Scheme_Native_Lambda *arg_n0; 161 Scheme_Object *arg_s1; 162 const Scheme_Object *arg_t1; 163 Scheme_Object **arg_S1; 164 int arg_i1; 165 intptr_t arg_l1; 166 Scheme_Object *arg_s2; 167 Scheme_Object **arg_S2; 168 int arg_i2; 169 void *arg_p2; 170 171 const char *arg_str0; 172 const char *arg_str1; 173 int arg_i3; 174 Scheme_Object **arg_S4; 175 176 Scheme_Thread *arg_p; 177 /* when a future thread is blocked while running this future, 178 `arg_p' s set along with the blocking-operation arguments to 179 indicate the future thread's (fake) Racket thread, which has the 180 runstack, etc. */ 181 struct Scheme_Current_LWC *lwc; 182 /* when a future thread is blocked while running this future, 183 if `want_lw' is set, then `lwc' points to information for 184 capturing a lightweight continuation */ 185 struct Scheme_Future_Thread_State *fts; 186 /* when a future thread is blocked while running this future, 187 `fts' is set to identify the future thread */ 188 189 struct Scheme_Lightweight_Continuation *suspended_lw; 190 /* holds a lightweight continuation captured for the operation, 191 if any */ 192 int maybe_suspended_lw; 193 /* set to 1 with suspended_lw untl test in runtime thread; this 194 extra flag avoids spinning if the suspended continuation 195 cannot be resumed in the main thread for some reason */ 196 197 void **suspended_lw_stack; /* for overflow handling */ 198 199 Scheme_Object *retval_s; 200 void *retval_p; /* use only with conservative GC */ 201 MZ_MARK_STACK_TYPE retval_m; 202 int retval_i; 203 signed char no_retval; 204 char retval_is_rs_plus_two; /* => special result handling for on-demand JIT */ 205 206 Scheme_Object **multiple_array; 207 int multiple_count; 208 209 Scheme_Object *tail_rator; 210 Scheme_Object **tail_rands; 211 int num_tail_rands; 212 213 Scheme_Object *retval; 214 struct future_t *prev; 215 struct future_t *next; 216 217 struct future_t *next_waiting_atomic; 218 struct future_t *next_waiting_lwc; 219 struct future_t *next_waiting_touch; 220 221 struct future_t *prev_in_fsema_queue; 222 struct future_t *next_in_fsema_queue; 223 224 int in_tracing_mode; 225 226 Scheme_Object *touching; /* a list of weak pointers to futures touching this one */ 227 } future_t; 228 229 typedef struct fsemaphore_t { 230 Scheme_Object so; 231 232 int ready; 233 mzrt_mutex *mut; 234 future_t *queue_front; 235 future_t *queue_end; 236 } fsemaphore_t; 237 238 /* Primitive instrumentation stuff */ 239 240 /* Signature flags for primitive invocations */ 241 #define SIG_ON_DEMAND 1 242 #define SIG_ALLOC 2 243 #define SIG_ALLOC_MARK_SEGMENT 3 244 #define SIG_ALLOC_VALUES 4 245 #define SIG_ALLOC_STRUCT 5 246 #define SIG_ALLOC_VECTOR 6 247 #define SIG_MAKE_FSEMAPHORE 7 248 #define SIG_FUTURE 8 249 #define SIG_WRONG_TYPE_EXN 9 250 #define SIG_TAIL_APPLY 10 251 #define SIG_APPLY_AFRESH 11 252 253 # include "jit_ts_protos.h" 254 255 extern Scheme_Object *scheme_force_value_same_mark_as_lightweight_continuation(Scheme_Object *v); 256 257 extern Scheme_Object **scheme_rtcall_on_demand(Scheme_Object **argv); 258 extern uintptr_t scheme_rtcall_alloc(void); 259 extern void scheme_rtcall_new_mark_segment(Scheme_Thread *p); 260 extern void scheme_rtcall_allocate_values(int count, Scheme_Thread *t); 261 extern Scheme_Structure *scheme_rtcall_allocate_structure(int argc, Scheme_Struct_Type *stype); 262 extern Scheme_Object *scheme_rtcall_allocate_vector(int count); 263 extern Scheme_Object *scheme_rtcall_make_fsemaphore(Scheme_Object *ready); 264 extern Scheme_Object *scheme_rtcall_make_future(Scheme_Object *proc); 265 extern Scheme_Object *scheme_rtcall_tail_apply(Scheme_Object *rator, int argc, Scheme_Object **argv); 266 extern Scheme_Object *scheme_rtcall_apply_with_new_stack(Scheme_Object *rator, int argc, Scheme_Object **argv, int multi); 267 268 int scheme_can_apply_native_in_future(Scheme_Object *proc); 269 270 void scheme_future_block_until_gc(); 271 void scheme_future_continue_after_gc(); 272 void scheme_check_future_work(); 273 void scheme_future_gc_pause(); 274 void scheme_future_check_custodians(); 275 int scheme_future_is_runtime_thread(); 276 277 #endif /* MZ_USE_FUTURES */ 278 279 /* always defined: */ 280 Scheme_Object *scheme_future(int argc, Scheme_Object *argv[]); 281 Scheme_Object *scheme_current_future(int argc, Scheme_Object *argv[]); 282 Scheme_Object *scheme_fsemaphore_p(int argc, Scheme_Object *argv[]); 283 284 Scheme_Object *scheme_fsemaphore_count(int argc, Scheme_Object *argv[]); 285 Scheme_Object *scheme_make_fsemaphore(int argc, Scheme_Object *argv[]); 286 Scheme_Object *scheme_make_fsemaphore_inl(Scheme_Object *ready); 287 Scheme_Object *scheme_fsemaphore_wait(int argc, Scheme_Object *argv[]); 288 Scheme_Object *scheme_fsemaphore_post(int argc, Scheme_Object *argv[]); 289 Scheme_Object *scheme_fsemaphore_try_wait(int argc, Scheme_Object *argv[]); 290 291 Scheme_Object *scheme_box_cas(int argc, Scheme_Object *argv[]); 292 293 #endif 294