/ Check-in [4c6dfec5]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Improvements to the TRACE macro in test_async.c. (CVS 3088)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1:4c6dfec54fc128644e066c04902433f8df30672e
User & Date: drh 2006-02-13 14:49:39
Context
2006-02-13
15:29
Fix a deadlock problem on the sqlite3async_wait test interface. Improvements to tracing in test_async.c. (CVS 3089) check-in: 58c6d501 user: drh tags: trunk
14:49
Improvements to the TRACE macro in test_async.c. (CVS 3088) check-in: 4c6dfec5 user: drh tags: trunk
13:50
I/O errors shut down all processing on the same file in test_async.c. (CVS 3087) check-in: 4366e712 user: drh tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/test_async.c.

102
103
104
105
106
107
108
109
110





111


112
113
114
115
116
117
118
119
120
...
311
312
313
314
315
316
317
318

319
320
321
322
323
324
325
...
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
...
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
...
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
....
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126

/* Forward references */
typedef struct AsyncWrite AsyncWrite;
typedef struct AsyncFile AsyncFile;

/* Enable for debugging */
#if 0
# define TRACE(X,Y) \
    fprintf(stderr,"THRD=%d: ", (int)pthread_self()); \





    fprintf(stderr,X,Y);


#else
# define TRACE(X,Y) /* noop */
#endif

/*
** THREAD SAFETY NOTES
**
** Basic rules:
**
................................................................................
};

/* 
** The AsyncFile structure is a subclass of OsFile used for asynchronous IO.
*/
struct AsyncFile {
  IoMethod *pMethod;   /* Must be first */
  int ioError;         /* Value of any asychronous error we have seen */	  i64 iOffset;         /* Current seek() offset in file */

  OsFile *pBaseRead;   /* Read handle to the underlying Os file */
  OsFile *pBaseWrite;  /* Write handle to the underlying Os file */
};

/*
** Add an entry to the end of the global write-op list. pWrite should point 
** to an AsyncWrite structure allocated using sqlite3OsMalloc().  The writer
................................................................................
  if( async.pQueueLast ){
    assert( async.pQueueFirst );
    async.pQueueLast->pNext = pWrite;
  }else{
    async.pQueueFirst = pWrite;
  }
  async.pQueueLast = pWrite;
  TRACE("PUSH %p\n", pWrite);

  /* 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);
................................................................................
    holdingMutex = 1;
    while( (p = async.pQueueFirst)==0 ){
      pthread_cond_broadcast(&async.emptySignal);
      if( async.writerHaltWhenIdle ){
        pthread_mutex_unlock(&async.queueMutex);
        break;
      }else{
        TRACE("IDLE\n", 0);
        pthread_cond_wait(&async.queueSignal, &async.queueMutex);
        TRACE("WAKEUP\n", 0);
      }
    }
    if( p==0 ) break;
    TRACE("PROCESSING %p\n", p);

    /* 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,
................................................................................
    ** 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 );

................................................................................
  int objc,
  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",0);
  pthread_cond_broadcast(&async.queueSignal);
  pthread_mutex_lock(&async.writerMutex);
  pthread_mutex_unlock(&async.writerMutex);
  return TCL_OK;
}









|
|
>
>
>
>
>
|
>
>

|







 







|
>







 







|







 







|

|



|







 







|







 







|







102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
...
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
...
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
...
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
...
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
....
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134

/* Forward references */
typedef struct AsyncWrite AsyncWrite;
typedef struct AsyncFile AsyncFile;

/* Enable for debugging */
#if 0
# define TRACE(X) 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);
}
#else
# define TRACE(X) /* noop */
#endif

/*
** THREAD SAFETY NOTES
**
** Basic rules:
**
................................................................................
};

/* 
** The AsyncFile structure is a subclass of OsFile used for asynchronous IO.
*/
struct AsyncFile {
  IoMethod *pMethod;   /* Must be first */
  int ioError;         /* Value of any asychronous error we have seen */
  i64 iOffset;         /* Current seek() offset in file */
  OsFile *pBaseRead;   /* Read handle to the underlying Os file */
  OsFile *pBaseWrite;  /* Write handle to the underlying Os file */
};

/*
** Add an entry to the end of the global write-op list. pWrite should point 
** to an AsyncWrite structure allocated using sqlite3OsMalloc().  The writer
................................................................................
  if( async.pQueueLast ){
    assert( async.pQueueFirst );
    async.pQueueLast->pNext = pWrite;
  }else{
    async.pQueueFirst = pWrite;
  }
  async.pQueueLast = pWrite;
  TRACE(("PUSH %p\n", pWrite));

  /* 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);
................................................................................
    holdingMutex = 1;
    while( (p = async.pQueueFirst)==0 ){
      pthread_cond_broadcast(&async.emptySignal);
      if( async.writerHaltWhenIdle ){
        pthread_mutex_unlock(&async.queueMutex);
        break;
      }else{
        TRACE(("IDLE\n"));
        pthread_cond_wait(&async.queueSignal, &async.queueMutex);
        TRACE(("WAKEUP\n"));
      }
    }
    if( p==0 ) break;
    TRACE(("PROCESSING %p\n", p));

    /* 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,
................................................................................
    ** 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 );

................................................................................
  int objc,
  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;
}