Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Fix a deadlock problem on the sqlite3async_wait test interface. Improvements to tracing in test_async.c. (CVS 3089) |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
58c6d501385c6f7656290e8451e28be3 |
User & Date: | drh 2006-02-13 15:29:33.000 |
Context
2006-02-13
| ||
17:03 | Add in-process file locking to test_async.c. The unix implementation of sqlite3OsFullPathname() now attempts to remove /./ and /../ elements from the path. (CVS 3090) (check-in: 42379c6230 user: drh tags: trunk) | |
15:29 | Fix a deadlock problem on the sqlite3async_wait test interface. Improvements to tracing in test_async.c. (CVS 3089) (check-in: 58c6d50138 user: drh tags: trunk) | |
14:49 | Improvements to the TRACE macro in test_async.c. (CVS 3088) (check-in: 4c6dfec54f user: drh tags: trunk) | |
Changes
Changes to src/test_async.c.
︙ | ︙ | |||
101 102 103 104 105 106 107 | #define MAX(x,y) ((x)>(y)?(x):(y)) /* Forward references */ typedef struct AsyncWrite AsyncWrite; typedef struct AsyncFile AsyncFile; /* Enable for debugging */ | | | < < < | 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 | #define MAX(x,y) ((x)>(y)?(x):(y)) /* Forward references */ typedef struct AsyncWrite AsyncWrite; typedef struct AsyncFile AsyncFile; /* Enable for debugging */ static int sqlite3async_trace = 0; # define TRACE(X) if( sqlite3async_trace ) asyncTrace X static void asyncTrace(const char *zFormat, ...){ char *z; va_list ap; va_start(ap, zFormat); z = sqlite3_vmprintf(zFormat, ap); va_end(ap); fprintf(stderr, "[%d] %s", (int)pthread_self(), z); free(z); } /* ** THREAD SAFETY NOTES ** ** Basic rules: ** ** * Both read and write access to the global write-op queue must be |
︙ | ︙ | |||
259 260 261 262 263 264 265 266 267 268 269 270 271 272 | #define ASYNC_OPENDIRECTORY 5 #define ASYNC_SETFULLSYNC 6 #define ASYNC_DELETE 7 #define ASYNC_OPENEXCLUSIVE 8 #define ASYNC_SYNCDIRECTORY 9 /* ** Entries on the write-op queue are instances of the AsyncWrite ** structure, defined here. ** ** The interpretation of the iOffset and nByte variables varies depending ** on the value of AsyncWrite.op: ** | > > > > > > > > | 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 | #define ASYNC_OPENDIRECTORY 5 #define ASYNC_SETFULLSYNC 6 #define ASYNC_DELETE 7 #define ASYNC_OPENEXCLUSIVE 8 #define ASYNC_SYNCDIRECTORY 9 /* Names of opcodes. Used for debugging only. ** Make sure these stay in sync with the macros above! */ static const char *azOpcodeName[] = { "NOOP", "WRITE", "SYNC", "TRUNCATE", "CLOSE", "OPENDIR", "SETFULLSYNC", "DELETE", "OPENEX", "SYNCDIR" }; /* ** Entries on the write-op queue are instances of the AsyncWrite ** structure, defined here. ** ** The interpretation of the iOffset and nByte variables varies depending ** on the value of AsyncWrite.op: ** |
︙ | ︙ | |||
347 348 349 350 351 352 353 | if( async.pQueueLast ){ assert( async.pQueueFirst ); async.pQueueLast->pNext = pWrite; }else{ async.pQueueFirst = pWrite; } async.pQueueLast = pWrite; | | | 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 | if( async.pQueueLast ){ assert( async.pQueueFirst ); async.pQueueLast->pNext = pWrite; }else{ async.pQueueFirst = pWrite; } async.pQueueLast = pWrite; TRACE(("PUSH %p (%s)\n", pWrite, azOpcodeName[pWrite->op])); /* Drop the queue mutex */ pthread_mutex_unlock(&async.queueMutex); /* The writer thread might have been idle because there was nothing ** on the write-op queue for it to do. So wake it up. */ pthread_cond_signal(&async.queueSignal); |
︙ | ︙ | |||
838 839 840 841 842 843 844 | }else{ TRACE(("IDLE\n")); pthread_cond_wait(&async.queueSignal, &async.queueMutex); TRACE(("WAKEUP\n")); } } if( p==0 ) break; | | | 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 | }else{ TRACE(("IDLE\n")); pthread_cond_wait(&async.queueSignal, &async.queueMutex); TRACE(("WAKEUP\n")); } } if( p==0 ) break; TRACE(("PROCESSING %p (%s)\n", p, azOpcodeName[p->op])); /* Right now this thread is holding the mutex on the write-op queue. ** Variable 'p' points to the first entry in the write-op queue. In ** the general case, we hold on to the mutex for the entire body of ** the loop. ** ** However in the cases enumerated below, we relinquish the mutex, |
︙ | ︙ | |||
961 962 963 964 965 966 967 | ** so that the AsyncWrite structure can be safely removed from the ** global write-op queue. */ if( !holdingMutex ){ pthread_mutex_lock(&async.queueMutex); holdingMutex = 1; } | | | 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 | ** so that the AsyncWrite structure can be safely removed from the ** global write-op queue. */ if( !holdingMutex ){ pthread_mutex_lock(&async.queueMutex); holdingMutex = 1; } /* TRACE(("UNLINK %p\n", p)); */ if( p==async.pQueueLast ){ async.pQueueLast = 0; } async.pQueueFirst = p->pNext; sqlite3OsFree(p); assert( holdingMutex ); |
︙ | ︙ | |||
1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 | Tcl_Obj *CONST objv[] ){ if( async.writerHaltNow==0 && async.writerHaltWhenIdle==0 ){ Tcl_AppendResult(interp, "would block forever", (char*)0); return TCL_ERROR; } TRACE(("WAIT\n")); pthread_cond_broadcast(&async.queueSignal); pthread_mutex_lock(&async.writerMutex); pthread_mutex_unlock(&async.writerMutex); return TCL_OK; } #endif /* OS_UNIX and THREADSAFE and defined(SQLITE_ENABLE_REDEF_IO) */ /* ** This routine registers the custom TCL commands defined in this ** module. This should be the only procedure visible from outside ** of this module. */ int Sqlitetestasync_Init(Tcl_Interp *interp){ #if OS_UNIX && THREADSAFE && defined(SQLITE_ENABLE_REDEF_IO) Tcl_CreateObjCommand(interp,"sqlite3async_enable",testAsyncEnable,0,0); Tcl_CreateObjCommand(interp,"sqlite3async_halt",testAsyncHalt,0,0); Tcl_CreateObjCommand(interp,"sqlite3async_delay",testAsyncDelay,0,0); Tcl_CreateObjCommand(interp,"sqlite3async_start",testAsyncStart,0,0); Tcl_CreateObjCommand(interp,"sqlite3async_wait",testAsyncWait,0,0); #endif /* OS_UNIX and THREADSAFE and defined(SQLITE_ENABLE_REDEF_IO) */ return TCL_OK; } | > > > > | 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 | Tcl_Obj *CONST objv[] ){ if( async.writerHaltNow==0 && async.writerHaltWhenIdle==0 ){ Tcl_AppendResult(interp, "would block forever", (char*)0); return TCL_ERROR; } TRACE(("WAIT\n")); pthread_mutex_lock(&async.queueMutex); pthread_cond_broadcast(&async.queueSignal); pthread_mutex_unlock(&async.queueMutex); pthread_mutex_lock(&async.writerMutex); pthread_mutex_unlock(&async.writerMutex); return TCL_OK; } #endif /* OS_UNIX and THREADSAFE and defined(SQLITE_ENABLE_REDEF_IO) */ /* ** This routine registers the custom TCL commands defined in this ** module. This should be the only procedure visible from outside ** of this module. */ int Sqlitetestasync_Init(Tcl_Interp *interp){ #if OS_UNIX && THREADSAFE && defined(SQLITE_ENABLE_REDEF_IO) Tcl_CreateObjCommand(interp,"sqlite3async_enable",testAsyncEnable,0,0); Tcl_CreateObjCommand(interp,"sqlite3async_halt",testAsyncHalt,0,0); Tcl_CreateObjCommand(interp,"sqlite3async_delay",testAsyncDelay,0,0); Tcl_CreateObjCommand(interp,"sqlite3async_start",testAsyncStart,0,0); Tcl_CreateObjCommand(interp,"sqlite3async_wait",testAsyncWait,0,0); Tcl_LinkVar(interp, "sqlite3async_trace", (char*)&sqlite3async_trace, TCL_LINK_INT); #endif /* OS_UNIX and THREADSAFE and defined(SQLITE_ENABLE_REDEF_IO) */ return TCL_OK; } |