| 1 | #ifndef USE_THREADS |
| 2 | #define MUTEX_LOCK(m) |
| 3 | #define MUTEX_UNLOCK(m) |
| 4 | #define MUTEX_INIT(m) |
| 5 | #define MUTEX_DESTROY(m) |
| 6 | #define COND_INIT(c) |
| 7 | #define COND_SIGNAL(c) |
| 8 | #define COND_BROADCAST(c) |
| 9 | #define COND_WAIT(c, m) |
| 10 | #define COND_DESTROY(c) |
| 11 | |
| 12 | #define THR |
| 13 | /* Rats: if dTHR is just blank then the subsequent ";" throws an error */ |
| 14 | #define dTHR extern int errno |
| 15 | #else |
| 16 | |
| 17 | #ifdef FAKE_THREADS |
| 18 | typedef struct thread *perl_thread; |
| 19 | /* With fake threads, thr is global(ish) so we don't need dTHR */ |
| 20 | #define dTHR extern int errno |
| 21 | |
| 22 | /* |
| 23 | * Note that SCHEDULE() is only callable from pp code (which |
| 24 | * must be expecting to be restarted). We'll have to do |
| 25 | * something a bit different for XS code. |
| 26 | */ |
| 27 | #define SCHEDULE() return schedule(), op |
| 28 | |
| 29 | #define MUTEX_LOCK(m) |
| 30 | #define MUTEX_UNLOCK(m) |
| 31 | #define MUTEX_INIT(m) |
| 32 | #define MUTEX_DESTROY(m) |
| 33 | #define COND_INIT(c) perl_cond_init(c) |
| 34 | #define COND_SIGNAL(c) perl_cond_signal(c) |
| 35 | #define COND_BROADCAST(c) perl_cond_broadcast(c) |
| 36 | #define COND_WAIT(c, m) STMT_START { \ |
| 37 | perl_cond_wait(c); \ |
| 38 | SCHEDULE(); \ |
| 39 | } STMT_END |
| 40 | #define COND_DESTROY(c) |
| 41 | |
| 42 | #else |
| 43 | /* POSIXish threads */ |
| 44 | typedef pthread_t perl_thread; |
| 45 | #ifdef OLD_PTHREADS_API |
| 46 | #define pthread_mutexattr_init(a) pthread_mutexattr_create(a) |
| 47 | #define pthread_mutexattr_settype(a,t) pthread_mutexattr_setkind_np(a,t) |
| 48 | #define pthread_key_create(k,d) pthread_keycreate(k,(pthread_destructor_t)(d)) |
| 49 | #else |
| 50 | #define pthread_mutexattr_default NULL |
| 51 | #endif /* OLD_PTHREADS_API */ |
| 52 | |
| 53 | #define MUTEX_INIT(m) \ |
| 54 | if (pthread_mutex_init((m), pthread_mutexattr_default)) \ |
| 55 | croak("panic: MUTEX_INIT"); \ |
| 56 | else 1 |
| 57 | #define MUTEX_LOCK(m) \ |
| 58 | if (pthread_mutex_lock((m))) croak("panic: MUTEX_LOCK"); else 1 |
| 59 | #define MUTEX_UNLOCK(m) \ |
| 60 | if (pthread_mutex_unlock((m))) croak("panic: MUTEX_UNLOCK"); else 1 |
| 61 | #define MUTEX_DESTROY(m) \ |
| 62 | if (pthread_mutex_destroy((m))) croak("panic: MUTEX_DESTROY"); else 1 |
| 63 | #define COND_INIT(c) \ |
| 64 | if (pthread_cond_init((c), NULL)) croak("panic: COND_INIT"); else 1 |
| 65 | #define COND_SIGNAL(c) \ |
| 66 | if (pthread_cond_signal((c))) croak("panic: COND_SIGNAL"); else 1 |
| 67 | #define COND_BROADCAST(c) \ |
| 68 | if (pthread_cond_broadcast((c))) croak("panic: COND_BROADCAST"); else 1 |
| 69 | #define COND_WAIT(c, m) \ |
| 70 | if (pthread_cond_wait((c), (m))) croak("panic: COND_WAIT"); else 1 |
| 71 | #define COND_DESTROY(c) \ |
| 72 | if (pthread_cond_destroy((c))) croak("panic: COND_DESTROY"); else 1 |
| 73 | /* XXX Add "old" (?) POSIX draft interface too */ |
| 74 | #ifdef OLD_PTHREADS_API |
| 75 | struct thread *getTHR _((void)); |
| 76 | #define THR getTHR() |
| 77 | #else |
| 78 | #define THR ((struct thread *) pthread_getspecific(thr_key)) |
| 79 | #endif /* OLD_PTHREADS_API */ |
| 80 | #define dTHR struct thread *thr = THR |
| 81 | #endif /* FAKE_THREADS */ |
| 82 | |
| 83 | struct thread { |
| 84 | perl_thread Tself; |
| 85 | |
| 86 | /* The fields that used to be global */ |
| 87 | SV ** Tstack_base; |
| 88 | SV ** Tstack_sp; |
| 89 | SV ** Tstack_max; |
| 90 | |
| 91 | #ifdef OP_IN_REGISTER |
| 92 | OP * Topsave; |
| 93 | #else |
| 94 | OP * Top; |
| 95 | #endif |
| 96 | |
| 97 | I32 * Tscopestack; |
| 98 | I32 Tscopestack_ix; |
| 99 | I32 Tscopestack_max; |
| 100 | |
| 101 | ANY * Tsavestack; |
| 102 | I32 Tsavestack_ix; |
| 103 | I32 Tsavestack_max; |
| 104 | |
| 105 | OP ** Tretstack; |
| 106 | I32 Tretstack_ix; |
| 107 | I32 Tretstack_max; |
| 108 | |
| 109 | I32 * Tmarkstack; |
| 110 | I32 * Tmarkstack_ptr; |
| 111 | I32 * Tmarkstack_max; |
| 112 | |
| 113 | SV ** Tcurpad; |
| 114 | |
| 115 | SV * TSv; |
| 116 | XPV * TXpv; |
| 117 | char Tbuf[2048]; /* should be a global locked by a mutex */ |
| 118 | char Ttokenbuf[256]; /* should be a global locked by a mutex */ |
| 119 | struct stat Tstatbuf; |
| 120 | struct tms Ttimesbuf; |
| 121 | |
| 122 | /* XXX What about regexp stuff? */ |
| 123 | |
| 124 | /* Now the fields that used to be "per interpreter" (even when global) */ |
| 125 | |
| 126 | /* XXX What about magic variables such as $/, $? and so on? */ |
| 127 | HV * Tdefstash; |
| 128 | HV * Tcurstash; |
| 129 | |
| 130 | SV ** Ttmps_stack; |
| 131 | I32 Ttmps_ix; |
| 132 | I32 Ttmps_floor; |
| 133 | I32 Ttmps_max; |
| 134 | |
| 135 | int Tin_eval; |
| 136 | OP * Trestartop; |
| 137 | int Tdelaymagic; |
| 138 | bool Tdirty; |
| 139 | U8 Tlocalizing; |
| 140 | COP * Tcurcop; |
| 141 | |
| 142 | CONTEXT * Tcxstack; |
| 143 | I32 Tcxstack_ix; |
| 144 | I32 Tcxstack_max; |
| 145 | |
| 146 | AV * Tcurstack; |
| 147 | AV * Tmainstack; |
| 148 | JMPENV * Ttop_env; |
| 149 | I32 Trunlevel; |
| 150 | |
| 151 | /* XXX Sort stuff, firstgv, secongv and so on? */ |
| 152 | |
| 153 | perl_mutex *Tthreadstart_mutexp; |
| 154 | HV * Tcvcache; |
| 155 | U32 Tthrflags; |
| 156 | |
| 157 | #ifdef FAKE_THREADS |
| 158 | perl_thread next, prev; /* Linked list of all threads */ |
| 159 | perl_thread next_run, prev_run; /* Linked list of runnable threads */ |
| 160 | perl_cond wait_queue; /* Wait queue that we are waiting on */ |
| 161 | IV private; /* Holds data across time slices */ |
| 162 | I32 savemark; /* Holds MARK for thread join values */ |
| 163 | #endif /* FAKE_THREADS */ |
| 164 | }; |
| 165 | |
| 166 | typedef struct thread *Thread; |
| 167 | |
| 168 | /* Values and macros for thrflags */ |
| 169 | #define THR_STATE_MASK 3 |
| 170 | #define THR_NORMAL 0 |
| 171 | #define THR_DETACHED 1 |
| 172 | #define THR_JOINED 2 |
| 173 | #define THR_DEAD 3 |
| 174 | |
| 175 | #define ThrSTATE(t) (t->Tthrflags & THR_STATE_MASK) |
| 176 | #define ThrSETSTATE(t, s) STMT_START { \ |
| 177 | (t)->Tthrflags &= ~THR_STATE_MASK; \ |
| 178 | (t)->Tthrflags |= (s); \ |
| 179 | DEBUG_L(fprintf(stderr, "thread 0x%lx set to state %d\n", \ |
| 180 | (unsigned long)(t), (s))); \ |
| 181 | } STMT_END |
| 182 | |
| 183 | typedef struct condpair { |
| 184 | perl_mutex mutex; |
| 185 | perl_cond owner_cond; |
| 186 | perl_cond cond; |
| 187 | Thread owner; |
| 188 | } condpair_t; |
| 189 | |
| 190 | #define MgMUTEXP(mg) (&((condpair_t *)(mg->mg_ptr))->mutex) |
| 191 | #define MgOWNERCONDP(mg) (&((condpair_t *)(mg->mg_ptr))->owner_cond) |
| 192 | #define MgCONDP(mg) (&((condpair_t *)(mg->mg_ptr))->cond) |
| 193 | #define MgOWNER(mg) ((condpair_t *)(mg->mg_ptr))->owner |
| 194 | |
| 195 | #undef stack_base |
| 196 | #undef stack_sp |
| 197 | #undef stack_max |
| 198 | #undef curstack |
| 199 | #undef mainstack |
| 200 | #undef markstack |
| 201 | #undef markstack_ptr |
| 202 | #undef markstack_max |
| 203 | #undef scopestack |
| 204 | #undef scopestack_ix |
| 205 | #undef scopestack_max |
| 206 | #undef savestack |
| 207 | #undef savestack_ix |
| 208 | #undef savestack_max |
| 209 | #undef retstack |
| 210 | #undef retstack_ix |
| 211 | #undef retstack_max |
| 212 | #undef curcop |
| 213 | #undef cxstack |
| 214 | #undef cxstack_ix |
| 215 | #undef cxstack_max |
| 216 | #undef defstash |
| 217 | #undef curstash |
| 218 | #undef tmps_stack |
| 219 | #undef tmps_floor |
| 220 | #undef tmps_ix |
| 221 | #undef tmps_max |
| 222 | #undef curpad |
| 223 | #undef Sv |
| 224 | #undef Xpv |
| 225 | #undef top_env |
| 226 | #undef runlevel |
| 227 | #undef in_eval |
| 228 | #undef restartop |
| 229 | #undef delaymagic |
| 230 | #undef dirty |
| 231 | #undef localizing |
| 232 | |
| 233 | #define self (thr->Tself) |
| 234 | #define stack_base (thr->Tstack_base) |
| 235 | #define stack_sp (thr->Tstack_sp) |
| 236 | #define stack_max (thr->Tstack_max) |
| 237 | #ifdef OP_IN_REGISTER |
| 238 | #define opsave (thr->Topsave) |
| 239 | #else |
| 240 | #undef op |
| 241 | #define op (thr->Top) |
| 242 | #endif |
| 243 | #define curcop (thr->Tcurcop) |
| 244 | #define stack (thr->Tstack) |
| 245 | #define curstack (thr->Tcurstack) |
| 246 | #define mainstack (thr->Tmainstack) |
| 247 | #define markstack (thr->Tmarkstack) |
| 248 | #define markstack_ptr (thr->Tmarkstack_ptr) |
| 249 | #define markstack_max (thr->Tmarkstack_max) |
| 250 | #define scopestack (thr->Tscopestack) |
| 251 | #define scopestack_ix (thr->Tscopestack_ix) |
| 252 | #define scopestack_max (thr->Tscopestack_max) |
| 253 | |
| 254 | #define savestack (thr->Tsavestack) |
| 255 | #define savestack_ix (thr->Tsavestack_ix) |
| 256 | #define savestack_max (thr->Tsavestack_max) |
| 257 | |
| 258 | #define retstack (thr->Tretstack) |
| 259 | #define retstack_ix (thr->Tretstack_ix) |
| 260 | #define retstack_max (thr->Tretstack_max) |
| 261 | |
| 262 | #define cxstack (thr->Tcxstack) |
| 263 | #define cxstack_ix (thr->Tcxstack_ix) |
| 264 | #define cxstack_max (thr->Tcxstack_max) |
| 265 | |
| 266 | #define curpad (thr->Tcurpad) |
| 267 | #define Sv (thr->TSv) |
| 268 | #define Xpv (thr->TXpv) |
| 269 | #define defstash (thr->Tdefstash) |
| 270 | #define curstash (thr->Tcurstash) |
| 271 | |
| 272 | #define tmps_stack (thr->Ttmps_stack) |
| 273 | #define tmps_ix (thr->Ttmps_ix) |
| 274 | #define tmps_floor (thr->Ttmps_floor) |
| 275 | #define tmps_max (thr->Ttmps_max) |
| 276 | |
| 277 | #define in_eval (thr->Tin_eval) |
| 278 | #define restartop (thr->Trestartop) |
| 279 | #define delaymagic (thr->Tdelaymagic) |
| 280 | #define dirty (thr->Tdirty) |
| 281 | #define localizing (thr->Tlocalizing) |
| 282 | |
| 283 | #define top_env (thr->Ttop_env) |
| 284 | #define runlevel (thr->Trunlevel) |
| 285 | |
| 286 | #define threadstart_mutexp (thr->Tthreadstart_mutexp) |
| 287 | #define cvcache (thr->Tcvcache) |
| 288 | #define thrflags (thr->Tthrflags) |
| 289 | #endif /* USE_THREADS */ |