SQLite

Check-in [4c6dfec54f]
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
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 4c6dfec54fc128644e066c04902433f8df30672e
User & Date: drh 2006-02-13 14:49:39.000
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: 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)
13:50
I/O errors shut down all processing on the same file in test_async.c. (CVS 3087) (check-in: 4366e71217 user: drh tags: trunk)
Changes
Unified Diff 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

/* 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:
**







|
>
>
>
>
|
>
|
>
>

|







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

/* 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:
**
311
312
313
314
315
316
317
318

319
320
321
322
323
324
325
};

/* 
** 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







|
>







318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
};

/* 
** 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
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
  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);







|







347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
  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);
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
    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,







|

|



|







832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
    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,
953
954
955
956
957
958
959
960
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;
    }
    TRACE("UNLINK %p\n", p);
    if( p==async.pQueueLast ){
      async.pQueueLast = 0;
    }
    async.pQueueFirst = p->pNext;
    sqlite3OsFree(p);
    assert( holdingMutex );








|







961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
    ** 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 );

1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
  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;
}









|







1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
  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;
}