thr_test.c
上传用户:romrleung
上传日期:2022-05-23
资源大小:18897k
文件大小:6k
源码类别:

MySQL数据库

开发平台:

Visual C++

  1. /* Testing of thread creation to find memory allocation bug
  2. ** This is coded to use as few extern functions as possible!
  3. **
  4. ** The program must be compiled to be multithreaded !
  5. **
  6. ** The problem is that when this program is run it will allocate more and more
  7. ** memory, so there is a memory leak in the thread handling. The problem is how
  8. ** to avoid is !
  9. **
  10. ** It looks like the bug is that the std library doesn't free thread
  11. ** specific variables if one uses a thread variable.
  12. ** If one compiles this program with -DREMOVE_BUG
  13. ** there is no memory leaks anymore!
  14. **
  15. ** This program is tested with Microsofts VC++ 5.0, but BC5.2 is also
  16. ** reported to have this bug.
  17. */
  18. #include <windows.h>
  19. #include <process.h>
  20. #include <stdio.h>
  21. #define TEST_COUNT 100000
  22. /*****************************************************************************
  23. ** The following is to emulate the posix thread interface
  24. *****************************************************************************/
  25. typedef HANDLE  pthread_t;
  26. typedef struct thread_attr {
  27. DWORD dwStackSize ;
  28. DWORD dwCreatingFlag ;
  29. int priority ;
  30. } pthread_attr_t ;
  31. typedef struct { int dummy; } pthread_condattr_t;
  32. typedef struct {
  33.         unsigned int msg;
  34.         pthread_t thread;
  35.         DWORD thread_id;
  36. } pthread_cond_t;
  37. typedef CRITICAL_SECTION pthread_mutex_t;
  38. #define pthread_mutex_init(A,B)  InitializeCriticalSection(A)
  39. #define pthread_mutex_lock(A)    (EnterCriticalSection(A),0)
  40. #define pthread_mutex_unlock(A)  LeaveCriticalSection(A)
  41. #define pthread_mutex_destroy(A) DeleteCriticalSection(A)
  42. #define pthread_handler_decl(A,B) unsigned __cdecl A(void *B)
  43. typedef unsigned (__cdecl *pthread_handler)(void *);
  44. #define pthread_self() GetCurrentThread()
  45. static unsigned int thread_count;
  46. static pthread_cond_t COND_thread_count;
  47. static pthread_mutex_t LOCK_thread_count;
  48. pthread_mutex_t THR_LOCK_malloc,THR_LOCK_open,THR_LOCK_keycache,
  49. THR_LOCK_lock,THR_LOCK_isam;
  50. /*
  51. ** We have tried to use '_beginthreadex' instead of '_beginthread' here
  52. ** but in this case the program leaks about 512 characters for each
  53. ** created thread !
  54. */
  55. int pthread_create(pthread_t *thread_id, pthread_attr_t *attr,
  56.    pthread_handler func, void *param)
  57. {
  58.   HANDLE hThread;
  59.  
  60.   hThread=(HANDLE)_beginthread(func,
  61.        attr->dwStackSize ? attr->dwStackSize :
  62.        65535,param);
  63.   if ((long) hThread == -1L)
  64.   {
  65.     return(errno ? errno : -1);
  66.   }
  67.   *thread_id=hThread;
  68.   return(0);
  69. }
  70. void pthread_exit(unsigned A)
  71. {
  72.   _endthread();
  73. }
  74. /*
  75. ** The following simple implementation of conds works as long as
  76. ** only one thread uses pthread_cond_wait at a time.
  77. ** This is coded very carefully to work with thr_lock.
  78. */
  79. static unsigned int WIN32_WAIT_SIGNAL= 30000; /* Start message to use */
  80. int pthread_cond_init(pthread_cond_t *cond, const pthread_condattr_t *attr)
  81. {
  82.   cond->msg=WIN32_WAIT_SIGNAL++;
  83.   cond->thread=(pthread_t) pthread_self(); /* For global conds */
  84. //IRENA
  85.   cond->thread_id=GetCurrentThreadId();
  86.   return 0;
  87. }
  88. int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)
  89. {
  90.   MSG msg ;
  91.   unsigned int msgCode=cond->msg;
  92.   cond->thread=(pthread_t) pthread_self();
  93. //IRENA
  94. //???  cond->thread_id=GetCurrentThreadId();
  95.   //VOID(ReleaseMutex(*mutex));
  96.   LeaveCriticalSection(mutex);
  97.   do
  98.   {
  99.     WaitMessage() ;
  100.     if (!PeekMessage(&msg, NULL, 1, 65534,PM_REMOVE))
  101.     {
  102.       return errno=GetLastError() ;
  103.     }
  104.   } while (msg.message != msgCode) ;
  105.   EnterCriticalSection(mutex);
  106.   return 0 ;
  107. }
  108. int pthread_cond_signal(pthread_cond_t *cond)
  109. {
  110.   if (!PostThreadMessage(cond->thread_id, cond->msg, 0,0))
  111.   {
  112.     return errno=GetLastError() ;
  113.   }
  114.   return 0 ;
  115. }
  116. int pthread_attr_init(pthread_attr_t *connect_att)
  117. {
  118.   connect_att->dwStackSize = 0;
  119.   connect_att->dwCreatingFlag = 0;
  120.   connect_att->priority = 0;
  121.   return 0;
  122. }
  123. int pthread_attr_setstacksize(pthread_attr_t *connect_att,DWORD stack)
  124. {
  125.   connect_att->dwStackSize=stack;
  126.   return 0;
  127. }
  128. int pthread_attr_setprio(pthread_attr_t *connect_att,int priority)
  129. {
  130.   connect_att->priority=priority;
  131.   return 0;
  132. }
  133. int pthread_attr_destroy(pthread_attr_t *connect_att)
  134. {
  135.   return 0;
  136. }
  137. /* from my_pthread.c */
  138. #ifndef REMOVE_BUG
  139. __declspec(thread) int THR_KEY_my_errno;
  140. int _my_errno(void)
  141. {
  142.   return THR_KEY_my_errno;
  143. }
  144. #endif
  145. /*****************************************************************************
  146. ** The test program
  147. *****************************************************************************/
  148. pthread_handler_decl(test_thread,arg)
  149. {
  150.   pthread_mutex_lock(&LOCK_thread_count);
  151.   thread_count--;
  152.   pthread_cond_signal(&COND_thread_count); /* Tell main we are ready */
  153.   pthread_mutex_unlock(&LOCK_thread_count);
  154.   pthread_exit(0);
  155.   return 0;
  156. }
  157. int main(int argc,char **argv)
  158. {
  159.   pthread_t tid;
  160.   pthread_attr_t thr_attr;
  161.   int i,error;
  162.   if ((error=pthread_cond_init(&COND_thread_count,NULL)))
  163.   {
  164.     fprintf(stderr,"Got error: %d from pthread_cond_init (errno: %d)",
  165.     error,errno);
  166.     exit(1);
  167.   }
  168.   pthread_mutex_init(&LOCK_thread_count,NULL);
  169.  if ((error=pthread_attr_init(&thr_attr)))
  170.   {
  171.     fprintf(stderr,"Got error: %d from pthread_attr_init (errno: %d)",
  172.     error,errno);
  173.     exit(1);
  174.   }
  175.   if ((error=pthread_attr_setstacksize(&thr_attr,65536L)))
  176.   {
  177.     fprintf(stderr,"Got error: %d from pthread_attr_setstacksize (errno: %d)",
  178.     error,errno);
  179.     exit(1);
  180.   }
  181.   printf("Init ok. Creating %d threadsn",TEST_COUNT);
  182.   for (i=1 ; i <= TEST_COUNT ; i++)
  183.   {
  184.     int *param= &i;
  185.     if ((i % 100) == 0)
  186.     {
  187.       printf("%8d",i);
  188.       fflush(stdout);
  189.     }
  190.     if ((error=pthread_mutex_lock(&LOCK_thread_count)))
  191.     {
  192.       fprintf(stderr,"nGot error: %d from pthread_mutex_lock (errno: %d)",
  193.       error,errno);
  194.       exit(1);
  195.     }
  196.     if ((error=pthread_create(&tid,&thr_attr,test_thread,(void*) param)))
  197.     {
  198.       fprintf(stderr,"nGot error: %d from pthread_create (errno: %d)n",
  199.       error,errno);
  200.       pthread_mutex_unlock(&LOCK_thread_count);
  201.       exit(1);
  202.     }
  203.     thread_count++;
  204.     pthread_mutex_unlock(&LOCK_thread_count);
  205.     if ((error=pthread_mutex_lock(&LOCK_thread_count)))
  206.       fprintf(stderr,"nGot error: %d from pthread_mutex_lockn",error);
  207.     while (thread_count)
  208.     {
  209.       if ((error=pthread_cond_wait(&COND_thread_count,&LOCK_thread_count)))
  210. fprintf(stderr,"nGot error: %d from pthread_cond_waitn",error);
  211.     }
  212.     pthread_mutex_unlock(&LOCK_thread_count);
  213.   }
  214.   pthread_attr_destroy(&thr_attr);
  215.   printf("nendn");
  216.   return 0;
  217. }