Changeset 431 for branches/thune
- Timestamp:
- 07/16/07 03:30:29 (17 months ago)
- Location:
- branches/thune/thread_safe
- Files:
-
- 14 modified
-
config.t (modified) (1 diff)
-
context.c (modified) (11 diffs)
-
eval.c (modified) (1 diff)
-
internal.h (modified) (2 diffs)
-
project.r (modified) (1 diff)
-
read_config.r (modified) (1 diff)
-
series.c (modified) (1 diff)
-
thread.c (modified) (10 diffs)
-
thune.c (modified) (7 diffs)
-
tokenize.c (modified) (1 diff)
-
unix/os.h (modified) (1 diff)
-
urlan.c (modified) (5 diffs)
-
urlan.h (modified) (1 diff)
-
win32/os.h (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
branches/thune/thread_safe/config.t
r426 r431 9 9 [x] dataflow "Component! datatype for dataflow programming" 10 10 11 [ ] threads "CPU Threads" 12 [ ] emh "Debugger Hooks" 11 13 [ ] dt-code "Include 'code datatype" 12 14 [ ] uds "Library with datatype & gc system only - no eval" 13 15 disable [bzip2 trig math3d dt-code] 14 16 15 [ ] threads "Experimental script threads"16 [ ] emh "Debugger Hooks"17 18 17 ;eof -
branches/thune/thread_safe/context.c
r427 r431 25 25 26 26 #define LOWERCASE(c) if(c >= 'A' && c <= 'Z') c -= 'A' - 'a' 27 28 29 /* 30 UrlanEnv::atoms & UrlanEnv::atomNames can be made thread safe through one 31 of the following: 32 33 1. Use LOCK_ATOMS in or around these functions: 34 ur_internT() 35 ur_atomStrT() 36 ur_atomCStrT() (and all use of returned pointer) 37 ur_atomHash() 38 dumpAtoms() 39 40 2. Fix size of atom arrays and throw error/assert when full. 41 Must still lock these functions to access head/chain AtomRec members: 42 ur_internT() 43 dumpAtoms() 44 45 Option #2 is currently being used. 46 */ 27 47 28 48 … … 120 140 void dumpAtoms( UThread* ut ) 121 141 { 122 LOCK_ GLOBAL142 LOCK_ATOMS 123 143 { 124 144 const char* names = ut->env->atomNames.ptr.c; … … 143 163 } 144 164 } 145 UNLOCK_ GLOBAL165 UNLOCK_ATOMS 146 166 } 147 167 #endif … … 151 171 Add atom to environment. 152 172 153 If the environment has multiple threads, the caller must have called154 LOCK_GLOBAL.155 156 173 \param str Name of atom. 157 174 \param len Number of characters. 158 175 159 \return sAtom176 \return Atom 160 177 */ 161 178 UAtom ur_internT( UThread* ut, const char* str, int len ) … … 171 188 AtomRec* node; 172 189 173 174 190 assert( len > 0 ); 175 191 176 192 177 193 // Check if atom already exists. 194 195 hash = ur_hash( str, str + len ); 196 197 LOCK_ATOMS 178 198 179 199 atoms = &ut->env->atoms; 180 200 table = (AtomRec*) atoms->ptr.v; 181 201 names = &ut->env->atomNames; 182 183 hash = ur_hash( str, str + len );184 202 185 203 node = table + (hash % atoms->avail); … … 228 246 // Nope, add new atom. 229 247 230 /* TODO: Make atoms & atomNames thread safe through one of the following:231 232 1. Halt all other threads.233 2. Fix size of atom arrays and throw error/assert when full.234 3. Use LOCK_GLOBAL in or around these functions in addition to ur_intern:235 ur_atomStrT()236 ur_atomCStrT()237 dumpAtoms()238 */239 240 248 if( atoms->used == atoms->avail ) 241 249 { 250 #if 1 251 // Atom table size is fixed so read only access does not need to be 252 // locked. When the table is full, we are finished. 253 assert( 0 && "Atom table is full" ); 254 return 0; // TODO: Report fatal error 255 #else 242 256 ur_arrayReserve( atoms, sizeof(AtomRec), atoms->used + 1 ); 243 257 ur_rebuildAtomHash( atoms ); … … 245 259 246 260 HASH_INSERT( atoms, table, node, hash, atoms->used ) 261 #endif 247 262 } 248 263 node = table + atoms->used; … … 253 268 node->nameLen = len; 254 269 270 #if 1 271 if( (names->used + len + 1) > names->avail ) 272 { 273 assert( 0 && "Atom name buffer is full" ); 274 return 0; // TODO: Report fatal error 275 } 276 #else 255 277 ur_arrayReserve( names, sizeof(char), names->used + len + 1 ); 278 #endif 279 256 280 cp = names->ptr.c + names->used; 257 281 ep = cp + len; … … 267 291 done: 268 292 269 return node - table; 293 c = node - table; 294 295 UNLOCK_ATOMS 296 297 return c; 270 298 } 271 299 … … 278 306 If added, the word is initialied as unset. 279 307 280 \return sIndex of word in context.308 \return Index of word in context. 281 309 */ 282 310 int ur_internWordT( UThread* ut, const UContext* ctx, UAtom atom ) … … 424 452 /** 425 453 Find word in context by atom. 426 \return sWord index or -1 if not found.454 \return Word index or -1 if not found. 427 455 */ 428 456 int ur_lookupT( UThread* ut, const UContext* ctx, UAtom atom ) -
branches/thune/thread_safe/eval.c
r429 r431 1765 1765 { uc_thread, "thread" }, 1766 1766 #endif 1767 #ifdef UR_CONFIG_TASKS 1768 { uc_task, "task" }, 1769 #endif 1767 1770 { uc_showTOS, "." }, 1768 1771 { uc_lift_local, "lift-local" }, -
branches/thune/thread_safe/internal.h
r428 r431 31 31 #define UNLOCK_GLOBAL mutexUnlock( ut->env->mutex ); 32 32 33 #define LOCK_ATOMS LOCK_GLOBAL 34 #define UNLOCK_ATOMS UNLOCK_GLOBAL 35 33 36 34 37 typedef struct … … 42 45 } 43 46 AtomRec; 47 48 49 /* 50 typedef struct 51 { 52 uint8_t type; 53 uint8_t flags; 54 uint16_t _pad0; 55 uint32_t _pad1; 56 OSThread thread; 57 } 58 UCellThread; 59 */ 44 60 45 61 -
branches/thune/thread_safe/project.r
r373 r431 93 93 ] 94 94 unix [ 95 libs %m 96 libs %bz2 95 libs {m bz2 pthread} 97 96 ] 98 97 win32 [ -
branches/thune/thread_safe/read_config.r
r426 r431 17 17 uds: 18 18 threads: 19 tasks: 19 20 macros: 20 21 emh: -
branches/thune/thread_safe/series.c
r428 r431 99 99 Get pointers to the start and end of a series or slice. 100 100 101 \return s101 \return 102 102 Pointer to UBinary if cell is a series or slice. 103 103 Otherwise, zero is returned. -
branches/thune/thread_safe/thread.c
r408 r431 38 38 39 39 40 extern UCellContext ur_thrGlobal; 41 40 42 UThread* ur_threadMake( UrlanEnv* env, int binCount, int blkCount ) 41 43 { … … 53 55 if( env->threads ) 54 56 { 57 #if 0 55 58 UThread* link = env->threads; 56 59 ut->nextThread = link->nextThread; 57 60 link->nextThread = ut; 61 #endif 58 62 } 59 63 else … … 71 75 //ur_hold( ut, UT_BINARY, binN ); // Hardcoded in recycle 72 76 } 77 78 // Make hold & global context blocks. 79 ur_makeBlock( 8 ); // 0 - BLK_THREAD_HOLD 80 ur_makeBlock( 1024 ); // 1 - BLK_GLOBAL_WORD 81 ur_makeBlock( 1024 ); // 2 - BLK_GLOBAL_VAL 82 ur_makeBlock( 1 ); // 3 - BLK_CTX_STACK 83 //ur_makeBlock( 0 ); // 4 - BLK_DSTACK 84 85 ur_pushContext( ut, (UCell*) &ur_thrGlobal ); 73 86 } 74 87 return ut; … … 76 89 77 90 78 #ifdef UR_CONFIG_THREADS 91 /* 79 92 void ur_threadUnlink( UThread* th ) 80 93 { … … 82 95 it = ((UrlanEnv*) th->env)->threads; 83 96 if( it == th ) 84 ((UrlanEnv*) th->env)->threads = (UThread*) th->nextThread; 85 while( it->nextThread != th ) 86 it = it->nextThread; 87 it->nextThread = th->nextThread; 97 ((UrlanEnv*) th->env)->threads = (UThread*) th->nextTask; 98 while( it->nextTask != th ) 99 it = it->nextTask; 100 it->nextTask = th->nextTask; 101 } 102 */ 103 104 105 #ifdef UR_CONFIG_TASKS 106 void ur_taskUnlink( UThread* th ) 107 { 108 UThread* it; 109 it = ((UrlanEnv*) th->env)->threads; 110 if( it == th ) 111 ((UrlanEnv*) th->env)->threads = (UThread*) th->nextTask; 112 while( it->nextTask != th ) 113 it = it->nextTask; 114 it->nextTask = th->nextTask; 88 115 } 89 116 90 117 91 118 // Returns zero and sets error if no threads are ready. 92 UThread* ur_t hreadNextReady( UThread* cur )119 UThread* ur_taskNextReady( UThread* cur ) 93 120 { 94 121 UThread* next = cur; … … 96 123 do 97 124 { 98 next = next->nextT hread;99 if( next->state == UR_T HREAD_READY )100 { 101 next->state = UR_T HREAD_RUNNING;125 next = next->nextTask; 126 if( next->state == UR_TASK_READY ) 127 { 128 next->state = UR_TASK_RUNNING; 102 129 return next; 103 130 } 104 else if( next->state == UR_T HREAD_BLOCKED )131 else if( next->state == UR_TASK_BLOCKED ) 105 132 { 106 133 UCell* pc; … … 113 140 if( pc && ! ur_is(pc, UT_UNSET) ) 114 141 { 115 next->state = UR_T HREAD_RUNNING;142 next->state = UR_TASK_RUNNING; 116 143 return next; 117 144 } … … 121 148 while( next != cur ); 122 149 123 ur_throwErr( cur, UR_EX_SCRIPT, "All t hreads are blocked" );150 ur_throwErr( cur, UR_EX_SCRIPT, "All tasks are blocked" ); 124 151 return 0; 125 152 } … … 145 172 */ 146 173 147 th->state = UR_T HREAD_READY;174 th->state = UR_TASK_READY; 148 175 th->callOp = 0; 149 176 th->tos = th->dstack; … … 183 210 184 211 /** 185 \return scell pointer to TOS.212 \return cell pointer to TOS. 186 213 Pops TOS if pop is non-zero. 187 214 */ -
branches/thune/thread_safe/thune.c
r427 r431 11 11 extern int ur_lessOrEqual( const UCell*, const UCell* ); 12 12 13 #ifdef UR_CONFIG_T HREADS14 extern void ur_t hreadUnlink( UThread* );15 extern UThread* ur_t hreadNextReady( UThread* );13 #ifdef UR_CONFIG_TASKS 14 extern void ur_taskUnlink( UThread* ); 15 extern UThread* ur_taskNextReady( UThread* ); 16 16 #endif 17 17 … … 164 164 165 165 #ifdef UR_CONFIG_THREADS 166 // (block -- ) 166 #ifdef _WIN32 167 static DWORD WINAPI threadRoutine( LPVOID arg ) 168 #else 169 static void* threadRoutine( void* arg ) 170 #endif 171 { 172 UThread* ut = (UThread*) arg; 173 ur_eval( ut, ut->tos[1].series.n, 0 ); 174 ur_threadFree( ut ); 175 return 0; 176 } 177 178 /* 179 static void ur_threadCloneCell( UThread* ut, UCell* cellA, 180 UThread* to, UCell* cellB ) 181 { 182 UIndex newBlkN; 183 184 switch( ur_type(cell) ) 185 { 186 case UT_BLOCK: 187 { 188 UBlock* blkA; 189 UBlock* blkB; 190 blkA = ur_blockPtr( blkN ); 191 newBlkN = ur_makeBlockT( to, blkA->used, &blkB ); 192 } 193 break; 194 195 case UT_STRING: 196 break; 197 } 198 } 199 */ 200 201 202 // (code -- ) 167 203 UR_CALL( uc_thread ) 168 204 { 205 if( ur_is(tos, UT_BLOCK) || ur_is(tos, UT_STRING) ) 206 { 207 UThread* thr = ur_threadMake( ut->env, 64, 128 ); 208 if( thr ) 209 { 210 OSThread pth; 211 #ifdef _WIN32 212 DWORD winId; 213 #endif 214 215 if( ur_is(tos, UT_STRING) ) 216 { 217 char* cpA; 218 char* cpB; 219 ur_seriesMem( ut, tos, &cpA, &cpB ); 220 thr->tos[1].series.n = ur_tokenize( thr, cpA, cpB ); 221 } 222 223 #ifdef _WIN32 224 pth = CreateThread( NULL, 0, threadRoutine, thr, 0, &winId ); 225 if( pth == NULL ) 226 #else 227 if( pthread_create( &pth, 0, threadRoutine, thr ) != 0 ) 228 #endif 229 { 230 ur_throwErr( UR_ERR_INTERNAL, "Could not create thread" ); 231 return; 232 } 233 234 #if 1 235 { 236 void* status; 237 pthread_join( pth, &status ); //KR 238 } 239 #endif 240 } 241 UR_S_DROP; 242 } 243 else 244 { 245 ur_throwErr( UR_ERR_DATATYPE, "thread expected block!/string!" ); 246 } 247 } 248 #endif 249 250 251 #ifdef UR_CONFIG_TASKS 252 // (block -- ) 253 UR_CALL( uc_task ) 254 { 169 255 if( ur_is(tos, UT_BLOCK) ) 170 256 { 171 257 UThread* thr; 172 258 UThread* save; 173 thr = ur_threadMake( ut->env );259 thr = ur_threadMake( ut->env, 32, 32 ); 174 260 if( thr ) 175 261 { … … 307 393 UCell* pc; 308 394 UCell* end; 309 #ifdef UR_CONFIG_T HREADS395 #ifdef UR_CONFIG_TASKS 310 396 int insCycle = 0; 311 397 #endif … … 323 409 execute: 324 410 325 #ifdef UR_CONFIG_T HREADS411 #ifdef UR_CONFIG_TASKS 326 412 if( ++insCycle == 100 ) 327 413 { 328 if( ut->nextT hread!= ut )329 { 330 ut->state = UR_T HREAD_READY;414 if( ut->nextTask != ut ) 415 { 416 ut->state = UR_TASK_READY; 331 417 switch_thread: 332 418 PUSHC_EVAL( blkN, start, pc ); 333 ut = ur_t hreadNextReady( ut );419 ut = ur_taskNextReady( ut ); 334 420 if( ! ut ) 335 421 goto error; … … 363 449 case UT_UNSET: 364 450 --pc; 365 #ifdef UR_CONFIG_T HREADS366 if( ut->nextT hread!= ut )367 { 368 ut->state = UR_T HREAD_BLOCKED;451 #ifdef UR_CONFIG_TASKS 452 if( ut->nextTask != ut ) 453 { 454 ut->state = UR_TASK_BLOCKED; 369 455 goto switch_thread; 370 456 } … … 956 1042 goto execute; 957 1043 958 #ifdef UR_CONFIG_T HREADS1044 #ifdef UR_CONFIG_TASKS 959 1045 case CC_TERM: 960 if( ut->nextT hread== ut )1046 if( ut->nextTask == ut ) 961 1047 goto finish; 962 term_t hread:1048 term_task: 963 1049 { 964 1050 UThread* thr = ut; 965 ut->state = UR_T HREAD_TERM;966 ut = ur_t hreadNextReady( ut );1051 ut->state = UR_TASK_TERM; 1052 ut = ur_taskNextReady( ut ); 967 1053 if( ! ut ) 968 1054 goto error; 969 ur_t hreadUnlink( thr );1055 ur_taskUnlink( thr ); 970 1056 ur_threadFree( thr ); 971 1057 } … … 974 1060 975 1061 case CC_END: 976 #ifdef UR_CONFIG_T HREADS977 if( ut->nextT hread!= ut )978 goto term_t hread;1062 #ifdef UR_CONFIG_TASKS 1063 if( ut->nextTask != ut ) 1064 goto term_task; 979 1065 #endif 980 1066 goto finish; -
branches/thune/thread_safe/tokenize.c
r427 r431 299 299 300 300 /** 301 \return Returns block index or zero if an error is thrown.301 \return Block index or zero if an error is thrown. 302 302 */ 303 303 UIndex ur_tokenize( UThread* ut, const char* it, const char* end ) -
branches/thune/thread_safe/unix/os.h
r387 r431 59 59 60 60 61 typedef pthread_t OSThread; 61 62 typedef pthread_mutex_t OSMutex; 62 63 63 #define mutexInit (mh) pthread_mutex_init(&mh,0)64 #define mutexFree(mh) pthread_mutex_destroy(&mh)65 #define mutexLock(mh) pthread_mutex_lock(&mh)66 #define mutexUnlock(mh) pthread_mutex_unlock(&mh)64 #define mutexInitF(mh) (pthread_mutex_init(&mh,0) == -1) 65 #define mutexFree(mh) pthread_mutex_destroy(&mh) 66 #define mutexLock(mh) pthread_mutex_lock(&mh) 67 #define mutexUnlock(mh) pthread_mutex_unlock(&mh) 67 68 68 69 -
branches/thune/thread_safe/urlan.c
r427 r431 411 411 int i; 412 412 413 //printf( "KR sizeof(pthread_t) = %lu\n", sizeof(pthread_t) ); 414 //assert( sizeof(UCellThread) == 16 ); 415 413 416 assert( sizeof(UCell) == 16 ); 414 417 //assert( sizeof(LocalFrame) == 16 ); … … 451 454 \param customCount Number of UDatatype in custom array. 452 455 453 \return sUR_EVAL_ code.456 \return UR_EVAL_ code. 454 457 */ 455 458 int ur_startup( UrlanEnv* env, UDatatype* custom, int customCount ) … … 467 470 env->dtCount = UT_BI_COUNT + customCount; 468 471 469 ur_arrayInit( &env->atoms, sizeof(AtomRec), 4096);470 ur_arrayInit( &env->atomNames, sizeof(char), 2048 );472 ur_arrayInit( &env->atoms, sizeof(AtomRec), 2048 ); 473 ur_arrayInit( &env->atomNames, sizeof(char), 2048 * 6 ); 471 474 ur_arrayInit( &env->devices, sizeof(UPortDevice*), 8 ); 472 475 ur_rebuildAtomHash( &env->atoms ); … … 485 488 // Init main thread. 486 489 487 if( mutexInit( env->mutex ) == -1 ) 488 { 489 #ifndef _WIN32 490 if( mutexInitF( env->mutex ) ) 491 { 492 #ifdef _WIN32 493 //GetLastError(); 494 #else 490 495 perror( "mutexInit" ); 491 496 #endif … … 495 500 ut = ur_threadMake( env, 512, 1024 ); 496 501 497 // Make hold & global context blocks.498 ur_makeBlock( 8 ); // 0 - BLK_THREAD_HOLD499 ur_makeBlock( 1024 ); // 1 - BLK_GLOBAL_WORD500 ur_makeBlock( 1024 ); // 2 - BLK_GLOBAL_VAL501 ur_makeBlock( 1 ); // 3 - BLK_CTX_STACK502 //ur_makeBlock( 0 ); // 4 - BLK_DSTACK503 504 ur_pushContext( ut, (UCell*) &ur_thrGlobal );505 506 {507 //UBlock* blk = ur_tblockPtr( BLK_DSTACK );508 }509 502 510 503 // Add datatypes first so UT_ defines match the index & atom. -
branches/thune/thread_safe/urlan.h
r427 r431
