一个非常简单的线程池,在 C++ 中使用 pthreads
我试图了解使用 POSIX pthreads 的一些基础知识。我(最终)需要做的事情是使用线程池模型并行化一些计算。目前我想确保我对 POSIX pthread 模型的工作原理有一个非常基本的了解。所以我试图创建最简单的线程池,它足够通用来完成我想做的事情。将会有一些共享内存、一个输入队列和一个输出队列,并且会有互斥体保护每个队列。我已经编写了一些代码来执行此操作,但 valgrind 的 helgrind 工具不喜欢我所做的。我怀疑我错过了一些基本的东西。您对我的代码有深入的了解吗?
#include <stdlib.h>
#include <string>
#include <sstream>
#include <list>
#include <iostream>
#include <pthread.h>
#include <signal.h>
#include <sys/select.h>
// the muticies, protectors of the shared resources
pthread_mutex_t coutLock;
pthread_mutex_t inQueueLock;
pthread_mutex_t outQueueLock;
// the shared data
std::list< std::string > inQueue;
std::list< std::string > outQueue;
struct thread_detail { // information to pass to worker threads
unsigned long num;
};
extern "C" {
void *workerThread(void *threadarg);
}
void *workerThread(void *threadarg)
{
struct thread_detail *my_data;
my_data = (thread_detail *) threadarg;
int taskid = my_data->num;
std::stringstream ss; ss<<taskid; std::string taskString(ss.str());
bool somethingTodo=true;
while (somethingTodo) // keep on working until inQueue is empty
{
pthread_mutex_lock( &inQueueLock );
std::string workOnMe;
if (inQueue.size()==0) { somethingTodo=false; }
else
{
workOnMe = inQueue.front();
inQueue.pop_front();
}
pthread_mutex_unlock( &inQueueLock );
if (!somethingTodo) break;
workOnMe = "thread " + taskString + " worked on " + workOnMe;
// let's pretend this takes some time, add a delay to the computation
struct timeval timeout;
timeout.tv_sec = 0; timeout.tv_usec = 100000; // 0.1 second delay
select( 0, NULL, NULL, NULL, & timeout );
pthread_mutex_lock( &outQueueLock );
outQueue.push_back( workOnMe );
pthread_mutex_unlock( &outQueueLock );
}
pthread_exit(NULL);
}
int main (int argc, char *argv[])
{
unsigned long comp_DONE=0;
unsigned long comp_START=0;
// set-up the mutexes
pthread_mutex_init( &coutLock, NULL );
pthread_mutex_init( &inQueueLock, NULL );
pthread_mutex_init( &outQueueLock, NULL );
if (argc != 3) { std::cout<<"Program requires two arguments: (1) number of threads to use,"
" and (2) tasks to accomplish.\n"; exit(1); }
unsigned long NUM_THREADS(atoi( argv[1] ));
unsigned long comp_TODO(atoi(argv[2]));
std::cout<<"Program will have "<<NUM_THREADS<<" threads, working on "<<comp_TODO<<" things \n";
for (unsigned long i=0; i<comp_TODO; i++) // fill inQueue will rubbish data since this isn't an actual computation...
{
std::stringstream ss;
ss<<"task "<<i;
inQueue.push_back(ss.str());
}
// start the worker threads
std::list< pthread_t* > threadIdList; // just the thread ids
std::list< thread_detail > thread_table; // for keeping track of information on the various threads we'll create
for (unsigned long i=0; i<NUM_THREADS; i++) // start the threads
{
pthread_t *tId( new pthread_t ); threadIdList.push_back(tId);
thread_detail Y; Y.num=i; thread_table.push_back(Y);
int rc( pthread_create( tId, NULL, workerThread, (void *)(&(thread_table.back() )) ) );
if (rc) { std::cout<<"ERROR; return code from pthread_create() "<<comp_START<<"\n"; std::cout.flush();
exit(-1); }
}
// now we wait for the threads to terminate, perhaps updating the screen with info as we go.
std::string stringOut;
while (comp_DONE != comp_TODO)
{
// poll the queue to get a status update on computation
pthread_mutex_lock(&inQueueLock);
comp_START = comp_TODO - inQueue.size();
pthread_mutex_unlock(&inQueueLock);
pthread_mutex_lock(&outQueueLock);
comp_DONE = outQueue.size();
pthread_mutex_unlock(&outQueueLock);
// update for users
pthread_mutex_lock(&coutLock);
for (unsigned long i=0; i<stringOut.length(); i++) std::cout<<"\b";
std::stringstream ss; ss<<"started "<<comp_START<<" completed "<<comp_DONE<<" of "<<comp_TODO;
stringOut = ss.str(); std::cout<<stringOut; std::cout.flush();
pthread_mutex_unlock(&coutLock);
// wait one second per update
struct timeval timeout;
timeout.tv_sec = 1; timeout.tv_usec = 0;
select( 0, NULL, NULL, NULL, & timeout );
} // big while loop
// call join to kill all worker threads
std::list< pthread_t* >::iterator i(threadIdList.begin());
while (i!=threadIdList.end())
{
if (pthread_join( *(*i), NULL)!=0) { std::cout<<"Thread join error!\n"; exit(1); }
delete (*i);
threadIdList.erase(i++);
}
std::cout<<"\n";
// let the user know what happened
for (std::list< std::string >::iterator i=outQueue.begin(); i!=outQueue.end(); i++)
{
std::cout<<(*i)<<"\n";
}
// clean-up
pthread_mutex_destroy(&coutLock);
pthread_mutex_destroy(&inQueueLock);
pthread_mutex_destroy(&outQueueLock);
// pthread_exit(NULL);
}
这是将参数 2 40 传递给编译程序时的 helgrind 输出。
valgrind -v --tool=helgrind ./thread1 2 40
==12394== Helgrind, a thread error detector
==12394== Copyright (C) 2007-2009, and GNU GPL'd, by OpenWorks LLP et al.
==12394== Using Valgrind-3.6.0.SVN-Debian and LibVEX; rerun with -h for copyright info
==12394== Command: ./thread1 2 40
==12394==
--12394-- Valgrind options:
--12394-- --suppressions=/usr/lib/valgrind/debian-libc6-dbg.supp
--12394-- -v
--12394-- --tool=helgrind
--12394-- Contents of /proc/version:
--12394-- Linux version 2.6.32-24-generic (buildd@yellow) (gcc version 4.4.3 (Ubuntu 4.4.3-4ubuntu5) ) #38-Ubuntu SMP Mon Jul 5 09:20:59 UTC 2010
--12394-- Arch and hwcaps: AMD64, amd64-sse3-cx16
--12394-- Page sizes: currently 4096, max supported 4096
--12394-- Valgrind library directory: /usr/lib/valgrind
--12394-- Reading syms from /home/rybu/prog/regina/exercise/thread1 (0x400000)
--12394-- Reading syms from /lib/ld-2.11.1.so (0x4000000)
--12394-- Reading debug info from /lib/ld-2.11.1.so ..
--12394-- .. CRC mismatch (computed 99d13f6f wanted 0962e544)
--12394-- Reading debug info from /usr/lib/debug/lib/ld-2.11.1.so ..
--12394-- Reading syms from /usr/lib/valgrind/helgrind-amd64-linux (0x38000000)
--12394-- object doesn't have a dynamic symbol table
--12394-- Reading suppressions file: /usr/lib/valgrind/debian-libc6-dbg.supp
--12394-- Reading suppressions file: /usr/lib/valgrind/default.supp
--12394-- Reading syms from /usr/lib/valgrind/vgpreload_core-amd64-linux.so (0x4a23000)
--12394-- Reading syms from /usr/lib/valgrind/vgpreload_helgrind-amd64-linux.so (0x4c25000)
--12394-- REDIR: 0x4018310 (index) redirected to 0x4c2be59 (index)
--12394-- REDIR: 0x4018390 (strcmp) redirected to 0x4c2bf4b (strcmp)
--12394-- REDIR: 0x40184a0 (strlen) redirected to 0x4c2bec5 (strlen)
--12394-- Reading syms from /usr/lib/libregina-engine-4.6.1.so (0x4e31000)
--12394-- Reading syms from /usr/lib/libgmp.so.3.5.2 (0x52f7000)
--12394-- Reading debug info from /usr/lib/libgmp.so.3.5.2 ..
--12394-- .. CRC mismatch (computed d65050b9 wanted 1e40f6c0)
--12394-- object doesn't have a symbol table
--12394-- Reading syms from /lib/libpthread-2.11.1.so (0x5557000)
--12394-- Reading debug info from /lib/libpthread-2.11.1.so ..
--12394-- .. CRC mismatch (computed 9da7e2f6 wanted 8161fac5)
--12394-- Reading debug info from /usr/lib/debug/lib/libpthread-2.11.1.so ..
--12394-- Reading syms from /lib/librt-2.11.1.so (0x5774000)
--12394-- Reading debug info from /lib/librt-2.11.1.so ..
--12394-- .. CRC mismatch (computed 0e4f4ece wanted 920c9bed)
--12394-- Reading debug info from /usr/lib/debug/lib/librt-2.11.1.so ..
--12394-- Reading syms from /lib/libz.so.1.2.3.3 (0x597c000)
--12394-- Reading debug info from /lib/libz.so.1.2.3.3 ..
--12394-- .. CRC mismatch (computed 86f1fa27 wanted 5f1ca823)
--12394-- object doesn't have a symbol table
--12394-- Reading syms from /usr/lib/libstdc++.so.6.0.13 (0x5b93000)
--12394-- Reading debug info from /usr/lib/libstdc++.so.6.0.13 ..
--12394-- .. CRC mismatch (computed 7b5bd5a5 wanted e2f63673)
--12394-- object doesn't have a symbol table
--12394-- Reading syms from /lib/libm-2.11.1.so (0x5ea7000)
--12394-- Reading debug info from /lib/libm-2.11.1.so ..
--12394-- .. CRC mismatch (computed 043548c3 wanted a081b93d)
--12394-- Reading debug info from /usr/lib/debug/lib/libm-2.11.1.so ..
--12394-- Reading syms from /lib/libgcc_s.so.1 (0x612a000)
--12394-- Reading debug info from /lib/libgcc_s.so.1 ..
--12394-- .. CRC mismatch (computed 7c01dfc9 wanted 9d78e511)
--12394-- object doesn't have a symbol table
--12394-- Reading syms from /lib/libc-2.11.1.so (0x6341000)
--12394-- Reading debug info from /lib/libc-2.11.1.so ..
--12394-- .. CRC mismatch (computed c73d5a83 wanted 02758e3e)
--12394-- Reading debug info from /usr/lib/debug/lib/libc-2.11.1.so ..
--12394-- Reading syms from /usr/lib/libxml2.so.2.7.6 (0x66c4000)
--12394-- Reading debug info from /usr/lib/libxml2.so.2.7.6 ..
--12394-- .. CRC mismatch (computed c2590bed wanted 7aaa27a0)
--12394-- Reading debug info from /usr/lib/debug/usr/lib/libxml2.so.2.7.6 ..
--12394-- Reading syms from /lib/libdl-2.11.1.so (0x6a14000)
--12394-- Reading debug info from /lib/libdl-2.11.1.so ..
--12394-- .. CRC mismatch (computed 4a29f474 wanted e0b8d72c)
--12394-- Reading debug info from /usr/lib/debug/lib/libdl-2.11.1.so ..
--12394-- REDIR: 0x55603c0 (pthread_mutex_lock) redirected to 0x4c299fb (pthread_mutex_lock)
--12394-- REDIR: 0x5561a00 (pthread_mutex_unlock) redirected to 0x4c29e8c (pthread_mutex_unlock)
--12394-- REDIR: 0x63bd520 (malloc) redirected to 0x4c28a06 (malloc)
--12394-- REDIR: 0x63bf360 (calloc) redirected to 0x4c27cc9 (calloc)
--12394-- REDIR: 0x5c5e380 (operator new[](unsigned long)) redirected to 0x4c28e97 (operator new[](unsigned long))
--12394-- REDIR: 0x5c5e250 (operator new(unsigned long)) redirected to 0x4c2921f (operator new(unsigned long))
--12394-- REDIR: 0x5c5c380 (operator delete(void*)) redirected to 0x4c28328 (operator delete(void*))
--12394-- REDIR: 0x5c5c3c0 (operator delete[](void*)) redirected to 0x4c27fa4 (operator delete[](void*))
--12394-- REDIR: 0x63c3fe0 (strlen) redirected to 0x4a235dc (_vgnU_ifunc_wrapper)
--12394-- REDIR: 0x63c4010 (__GI_strlen) redirected to 0x4c2be91 (strlen)
--12394-- REDIR: 0x63c7c60 (memcpy) redirected to 0x4c2bfdb (memcpy)
Program will have 2 threads, working on 40 things
--12394-- REDIR: 0x555dd60 (pthread_create@@GLIBC_2.2.5) redirected to 0x4c2d4c7 (pthread_create@*)
==12394== Thread #2 was created
==12394== at 0x64276BE: clone (clone.S:77)
==12394== by 0x555E172: pthread_create@@GLIBC_2.2.5 (createthread.c:75)
==12394== by 0x4C2D42C: pthread_create_WRK (hg_intercepts.c:230)
==12394== by 0x4C2D4CF: pthread_create@* (hg_intercepts.c:257)
==12394== by 0x401C22: main (in /home/rybu/prog/regina/exercise/thread1)
==12394==
==12394== Thread #1 is the program's root thread
==12394==
==12394== Possible data race during write of size 8 at 0x7fefffcf0 by thread #2
==12394== at 0x4C2D54C: mythread_wrapper (hg_intercepts.c:200)
==12394== This conflicts with a previous read of size 8 by thread #1
==12394== at 0x4C2D440: pthread_create_WRK (hg_intercepts.c:235)
==12394== by 0x4C2D4CF: pthread_create@* (hg_intercepts.c:257)
==12394== by 0x401C22: main (in /home/rybu/prog/regina/exercise/thread1)
==12394==
started 21 completed 19 of 40==12394== Thread #3 was created
==12394== at 0x64276BE: clone (clone.S:77)
==12394== by 0x555E172: pthread_create@@GLIBC_2.2.5 (createthread.c:75)
==12394== by 0x4C2D42C: pthread_create_WRK (hg_intercepts.c:230)
==12394== by 0x4C2D4CF: pthread_create@* (hg_intercepts.c:257)
==12394== by 0x401C22: main (in /home/rybu/prog/regina/exercise/thread1)
==12394==
==12394== Possible data race during read of size 1 at 0x63401a7 by thread #3
==12394== at 0x613A4D7: ??? (in /lib/libgcc_s.so.1)
==12394== by 0x613A947: _Unwind_Resume (in /lib/libgcc_s.so.1)
==12394== by 0x4019C9: workerThread(void*) (in /home/rybu/prog/regina/exercise/thread1)
==12394== by 0x4C2D558: mythread_wrapper (hg_intercepts.c:202)
==12394== by 0x555D9C9: start_thread (pthread_create.c:300)
==12394== by 0x64276FC: clone (clone.S:112)
==12394== This conflicts with a previous write of size 1 by thread #2
==12394== at 0x6138331: ??? (in /lib/libgcc_s.so.1)
==12394== by 0x5563F42: pthread_once (pthread_once.S:104)
==12394== by 0x613A4C9: ??? (in /lib/libgcc_s.so.1)
==12394== by 0x613A7B6: _Unwind_ForcedUnwind (in /lib/libgcc_s.so.1)
==12394== by 0x556508F: __pthread_unwind (unwind.c:130)
==12394== by 0x555EEB4: pthread_exit (pthreadP.h:265)
==12394== by 0x40198E: workerThread(void*) (in /home/rybu/prog/regina/exercise/thread1)
==12394== by 0x4C2D558: mythread_wrapper (hg_intercepts.c:202)
==12394==
==12394== Possible data race during read of size 1 at 0x63401a6 by thread #3
==12394== at 0x6139A12: ??? (in /lib/libgcc_s.so.1)
==12394== by 0x6139AA8: ??? (in /lib/libgcc_s.so.1)
==12394== by 0x613A724: ??? (in /lib/libgcc_s.so.1)
==12394== by 0x613A982: _Unwind_Resume (in /lib/libgcc_s.so.1)
==12394== by 0x4019C9: workerThread(void*) (in /home/rybu/prog/regina/exercise/thread1)
==12394== by 0x4C2D558: mythread_wrapper (hg_intercepts.c:202)
==12394== by 0x555D9C9: start_thread (pthread_create.c:300)
==12394== by 0x64276FC: clone (clone.S:112)
==12394== This conflicts with a previous write of size 1 by thread #2
==12394== at 0x613832A: ??? (in /lib/libgcc_s.so.1)
==12394== by 0x5563F42: pthread_once (pthread_once.S:104)
==12394== by 0x613A4C9: ??? (in /lib/libgcc_s.so.1)
==12394== by 0x613A7B6: _Unwind_ForcedUnwind (in /lib/libgcc_s.so.1)
==12394== by 0x556508F: __pthread_unwind (unwind.c:130)
==12394== by 0x555EEB4: pthread_exit (pthreadP.h:265)
==12394== by 0x40198E: workerThread(void*) (in /home/rybu/prog/regina/exercise/thread1)
==12394== by 0x4C2D558: mythread_wrapper (hg_intercepts.c:202)
==12394==
==12394== Possible data race during read of size 1 at 0x63401b0 by thread #3
==12394== at 0x6139AD7: ??? (in /lib/libgcc_s.so.1)
==12394== by 0x613A724: ??? (in /lib/libgcc_s.so.1)
==12394== by 0x613A982: _Unwind_Resume (in /lib/libgcc_s.so.1)
==12394== by 0x4019C9: workerThread(void*) (in /home/rybu/prog/regina/exercise/thread1)
==12394== by 0x4C2D558: mythread_wrapper (hg_intercepts.c:202)
==12394== by 0x555D9C9: start_thread (pthread_create.c:300)
==12394== by 0x64276FC: clone (clone.S:112)
==12394== This conflicts with a previous write of size 1 by thread #2
==12394== at 0x6138370: ??? (in /lib/libgcc_s.so.1)
==12394== by 0x5563F42: pthread_once (pthread_once.S:104)
==12394== by 0x613A4C9: ??? (in /lib/libgcc_s.so.1)
==12394== by 0x613A7B6: _Unwind_ForcedUnwind (in /lib/libgcc_s.so.1)
==12394== by 0x556508F: __pthread_unwind (unwind.c:130)
==12394== by 0x555EEB4: pthread_exit (pthreadP.h:265)
==12394== by 0x40198E: workerThread(void*) (in /home/rybu/prog/regina/exercise/thread1)
==12394== by 0x4C2D558: mythread_wrapper (hg_intercepts.c:202)
==12394==
--12394-- REDIR: 0x63bede0 (free) redirected to 0x4c28616 (free)
started 40 completed 40 of 40--12394-- REDIR: 0x555ef30 (pthread_join) redirected to 0x4c29796 (pthread_join)
thread 0 worked on task 0
thread 1 worked on task 1
thread 0 worked on task 2
thread 1 worked on task 3
thread 0 worked on task 4
thread 1 worked on task 5
thread 0 worked on task 6
thread 1 worked on task 7
thread 0 worked on task 8
thread 1 worked on task 9
thread 0 worked on task 10
thread 1 worked on task 11
thread 0 worked on task 12
thread 1 worked on task 13
thread 0 worked on task 14
thread 1 worked on task 15
thread 0 worked on task 16
thread 1 worked on task 17
thread 0 worked on task 18
thread 1 worked on task 19
thread 0 worked on task 20
thread 1 worked on task 21
thread 0 worked on task 22
thread 1 worked on task 23
thread 0 worked on task 24
thread 1 worked on task 25
thread 0 worked on task 26
thread 1 worked on task 27
thread 0 worked on task 28
thread 1 worked on task 29
thread 0 worked on task 30
thread 1 worked on task 31
thread 0 worked on task 32
thread 1 worked on task 33
thread 0 worked on task 34
thread 1 worked on task 35
thread 0 worked on task 36
thread 1 worked on task 37
thread 0 worked on task 38
thread 1 worked on task 39
==12394==
==12394== ERROR SUMMARY: 7 errors from 4 contexts (suppressed: 804 from 64)
==12394==
==12394== 1 errors in context 1 of 4:
==12394== Possible data race during read of size 1 at 0x63401a7 by thread #3
==12394== at 0x613A4D7: ??? (in /lib/libgcc_s.so.1)
==12394== by 0x613A947: _Unwind_Resume (in /lib/libgcc_s.so.1)
==12394== by 0x4019C9: workerThread(void*) (in /home/rybu/prog/regina/exercise/thread1)
==12394== by 0x4C2D558: mythread_wrapper (hg_intercepts.c:202)
==12394== by 0x555D9C9: start_thread (pthread_create.c:300)
==12394== by 0x64276FC: clone (clone.S:112)
==12394== This conflicts with a previous write of size 1 by thread #2
==12394== at 0x6138331: ??? (in /lib/libgcc_s.so.1)
==12394== by 0x5563F42: pthread_once (pthread_once.S:104)
==12394== by 0x613A4C9: ??? (in /lib/libgcc_s.so.1)
==12394== by 0x613A7B6: _Unwind_ForcedUnwind (in /lib/libgcc_s.so.1)
==12394== by 0x556508F: __pthread_unwind (unwind.c:130)
==12394== by 0x555EEB4: pthread_exit (pthreadP.h:265)
==12394== by 0x40198E: workerThread(void*) (in /home/rybu/prog/regina/exercise/thread1)
==12394== by 0x4C2D558: mythread_wrapper (hg_intercepts.c:202)
==12394==
==12394==
==12394== 2 errors in context 2 of 4:
==12394== Possible data race during read of size 1 at 0x63401b0 by thread #3
==12394== at 0x6139AD7: ??? (in /lib/libgcc_s.so.1)
==12394== by 0x613A724: ??? (in /lib/libgcc_s.so.1)
==12394== by 0x613A982: _Unwind_Resume (in /lib/libgcc_s.so.1)
==12394== by 0x4019C9: workerThread(void*) (in /home/rybu/prog/regina/exercise/thread1)
==12394== by 0x4C2D558: mythread_wrapper (hg_intercepts.c:202)
==12394== by 0x555D9C9: start_thread (pthread_create.c:300)
==12394== by 0x64276FC: clone (clone.S:112)
==12394== This conflicts with a previous write of size 1 by thread #2
==12394== at 0x6138370: ??? (in /lib/libgcc_s.so.1)
==12394== by 0x5563F42: pthread_once (pthread_once.S:104)
==12394== by 0x613A4C9: ??? (in /lib/libgcc_s.so.1)
==12394== by 0x613A7B6: _Unwind_ForcedUnwind (in /lib/libgcc_s.so.1)
==12394== by 0x556508F: __pthread_unwind (unwind.c:130)
==12394== by 0x555EEB4: pthread_exit (pthreadP.h:265)
==12394== by 0x40198E: workerThread(void*) (in /home/rybu/prog/regina/exercise/thread1)
==12394== by 0x4C2D558: mythread_wrapper (hg_intercepts.c:202)
==12394==
==12394==
==12394== 2 errors in context 3 of 4:
==12394== Possible data race during read of size 1 at 0x63401a6 by thread #3
==12394== at 0x6139A12: ??? (in /lib/libgcc_s.so.1)
==12394== by 0x6139AA8: ??? (in /lib/libgcc_s.so.1)
==12394== by 0x613A724: ??? (in /lib/libgcc_s.so.1)
==12394== by 0x613A982: _Unwind_Resume (in /lib/libgcc_s.so.1)
==12394== by 0x4019C9: workerThread(void*) (in /home/rybu/prog/regina/exercise/thread1)
==12394== by 0x4C2D558: mythread_wrapper (hg_intercepts.c:202)
==12394== by 0x555D9C9: start_thread (pthread_create.c:300)
==12394== by 0x64276FC: clone (clone.S:112)
==12394== This conflicts with a previous write of size 1 by thread #2
==12394== at 0x613832A: ??? (in /lib/libgcc_s.so.1)
==12394== by 0x5563F42: pthread_once (pthread_once.S:104)
==12394== by 0x613A4C9: ??? (in /lib/libgcc_s.so.1)
==12394== by 0x613A7B6: _Unwind_ForcedUnwind (in /lib/libgcc_s.so.1)
==12394== by 0x556508F: __pthread_unwind (unwind.c:130)
==12394== by 0x555EEB4: pthread_exit (pthreadP.h:265)
==12394== by 0x40198E: workerThread(void*) (in /home/rybu/prog/regina/exercise/thread1)
==12394== by 0x4C2D558: mythread_wrapper (hg_intercepts.c:202)
==12394==
==12394==
==12394== 2 errors in context 4 of 4:
==12394== Possible data race during write of size 8 at 0x7fefffcf0 by thread #2
==12394== at 0x4C2D54C: mythread_wrapper (hg_intercepts.c:200)
==12394== This conflicts with a previous read of size 8 by thread #1
==12394== at 0x4C2D440: pthread_create_WRK (hg_intercepts.c:235)
==12394== by 0x4C2D4CF: pthread_create@* (hg_intercepts.c:257)
==12394== by 0x401C22: main (in /home/rybu/prog/regina/exercise/thread1)
==12394==
--12394--
--12394-- used_suppression: 610 helgrind-glibc2X-101
--12394-- used_suppression: 192 helgrind---...-*Unwind*-*pthread_unwind*
--12394-- used_suppression: 2 helgrind-glibc2X-112
==12394==
==12394== ERROR SUMMARY: 7 errors from 4 contexts (suppressed: 804 from 64)
在解释 helgrind 输出时我不太有信心。
感谢您的任何见解。
I'm trying to understand some of the basics of using POSIX pthreads. The kind of thing I need to do (eventually) is parallelize some computations, using a thread pool model. At present I want to ensure I have a very basic sense for how the POSIX pthread model works. So I'm trying to create the simplest thread pool that's general enough to do the kinds of things I want to do. There will be some shared memory, an input queue, and an output queue, and there will be mutexes protecting each. I've written some code that does just that but valgrind's helgrind tool does not like what I've done. I suspect I'm missing something basic. Do you have insights into my code?
#include <stdlib.h>
#include <string>
#include <sstream>
#include <list>
#include <iostream>
#include <pthread.h>
#include <signal.h>
#include <sys/select.h>
// the muticies, protectors of the shared resources
pthread_mutex_t coutLock;
pthread_mutex_t inQueueLock;
pthread_mutex_t outQueueLock;
// the shared data
std::list< std::string > inQueue;
std::list< std::string > outQueue;
struct thread_detail { // information to pass to worker threads
unsigned long num;
};
extern "C" {
void *workerThread(void *threadarg);
}
void *workerThread(void *threadarg)
{
struct thread_detail *my_data;
my_data = (thread_detail *) threadarg;
int taskid = my_data->num;
std::stringstream ss; ss<<taskid; std::string taskString(ss.str());
bool somethingTodo=true;
while (somethingTodo) // keep on working until inQueue is empty
{
pthread_mutex_lock( &inQueueLock );
std::string workOnMe;
if (inQueue.size()==0) { somethingTodo=false; }
else
{
workOnMe = inQueue.front();
inQueue.pop_front();
}
pthread_mutex_unlock( &inQueueLock );
if (!somethingTodo) break;
workOnMe = "thread " + taskString + " worked on " + workOnMe;
// let's pretend this takes some time, add a delay to the computation
struct timeval timeout;
timeout.tv_sec = 0; timeout.tv_usec = 100000; // 0.1 second delay
select( 0, NULL, NULL, NULL, & timeout );
pthread_mutex_lock( &outQueueLock );
outQueue.push_back( workOnMe );
pthread_mutex_unlock( &outQueueLock );
}
pthread_exit(NULL);
}
int main (int argc, char *argv[])
{
unsigned long comp_DONE=0;
unsigned long comp_START=0;
// set-up the mutexes
pthread_mutex_init( &coutLock, NULL );
pthread_mutex_init( &inQueueLock, NULL );
pthread_mutex_init( &outQueueLock, NULL );
if (argc != 3) { std::cout<<"Program requires two arguments: (1) number of threads to use,"
" and (2) tasks to accomplish.\n"; exit(1); }
unsigned long NUM_THREADS(atoi( argv[1] ));
unsigned long comp_TODO(atoi(argv[2]));
std::cout<<"Program will have "<<NUM_THREADS<<" threads, working on "<<comp_TODO<<" things \n";
for (unsigned long i=0; i<comp_TODO; i++) // fill inQueue will rubbish data since this isn't an actual computation...
{
std::stringstream ss;
ss<<"task "<<i;
inQueue.push_back(ss.str());
}
// start the worker threads
std::list< pthread_t* > threadIdList; // just the thread ids
std::list< thread_detail > thread_table; // for keeping track of information on the various threads we'll create
for (unsigned long i=0; i<NUM_THREADS; i++) // start the threads
{
pthread_t *tId( new pthread_t ); threadIdList.push_back(tId);
thread_detail Y; Y.num=i; thread_table.push_back(Y);
int rc( pthread_create( tId, NULL, workerThread, (void *)(&(thread_table.back() )) ) );
if (rc) { std::cout<<"ERROR; return code from pthread_create() "<<comp_START<<"\n"; std::cout.flush();
exit(-1); }
}
// now we wait for the threads to terminate, perhaps updating the screen with info as we go.
std::string stringOut;
while (comp_DONE != comp_TODO)
{
// poll the queue to get a status update on computation
pthread_mutex_lock(&inQueueLock);
comp_START = comp_TODO - inQueue.size();
pthread_mutex_unlock(&inQueueLock);
pthread_mutex_lock(&outQueueLock);
comp_DONE = outQueue.size();
pthread_mutex_unlock(&outQueueLock);
// update for users
pthread_mutex_lock(&coutLock);
for (unsigned long i=0; i<stringOut.length(); i++) std::cout<<"\b";
std::stringstream ss; ss<<"started "<<comp_START<<" completed "<<comp_DONE<<" of "<<comp_TODO;
stringOut = ss.str(); std::cout<<stringOut; std::cout.flush();
pthread_mutex_unlock(&coutLock);
// wait one second per update
struct timeval timeout;
timeout.tv_sec = 1; timeout.tv_usec = 0;
select( 0, NULL, NULL, NULL, & timeout );
} // big while loop
// call join to kill all worker threads
std::list< pthread_t* >::iterator i(threadIdList.begin());
while (i!=threadIdList.end())
{
if (pthread_join( *(*i), NULL)!=0) { std::cout<<"Thread join error!\n"; exit(1); }
delete (*i);
threadIdList.erase(i++);
}
std::cout<<"\n";
// let the user know what happened
for (std::list< std::string >::iterator i=outQueue.begin(); i!=outQueue.end(); i++)
{
std::cout<<(*i)<<"\n";
}
// clean-up
pthread_mutex_destroy(&coutLock);
pthread_mutex_destroy(&inQueueLock);
pthread_mutex_destroy(&outQueueLock);
// pthread_exit(NULL);
}
Here is the helgrind output when passing the arguments 2 40 to the compiled program.
valgrind -v --tool=helgrind ./thread1 2 40
==12394== Helgrind, a thread error detector
==12394== Copyright (C) 2007-2009, and GNU GPL'd, by OpenWorks LLP et al.
==12394== Using Valgrind-3.6.0.SVN-Debian and LibVEX; rerun with -h for copyright info
==12394== Command: ./thread1 2 40
==12394==
--12394-- Valgrind options:
--12394-- --suppressions=/usr/lib/valgrind/debian-libc6-dbg.supp
--12394-- -v
--12394-- --tool=helgrind
--12394-- Contents of /proc/version:
--12394-- Linux version 2.6.32-24-generic (buildd@yellow) (gcc version 4.4.3 (Ubuntu 4.4.3-4ubuntu5) ) #38-Ubuntu SMP Mon Jul 5 09:20:59 UTC 2010
--12394-- Arch and hwcaps: AMD64, amd64-sse3-cx16
--12394-- Page sizes: currently 4096, max supported 4096
--12394-- Valgrind library directory: /usr/lib/valgrind
--12394-- Reading syms from /home/rybu/prog/regina/exercise/thread1 (0x400000)
--12394-- Reading syms from /lib/ld-2.11.1.so (0x4000000)
--12394-- Reading debug info from /lib/ld-2.11.1.so ..
--12394-- .. CRC mismatch (computed 99d13f6f wanted 0962e544)
--12394-- Reading debug info from /usr/lib/debug/lib/ld-2.11.1.so ..
--12394-- Reading syms from /usr/lib/valgrind/helgrind-amd64-linux (0x38000000)
--12394-- object doesn't have a dynamic symbol table
--12394-- Reading suppressions file: /usr/lib/valgrind/debian-libc6-dbg.supp
--12394-- Reading suppressions file: /usr/lib/valgrind/default.supp
--12394-- Reading syms from /usr/lib/valgrind/vgpreload_core-amd64-linux.so (0x4a23000)
--12394-- Reading syms from /usr/lib/valgrind/vgpreload_helgrind-amd64-linux.so (0x4c25000)
--12394-- REDIR: 0x4018310 (index) redirected to 0x4c2be59 (index)
--12394-- REDIR: 0x4018390 (strcmp) redirected to 0x4c2bf4b (strcmp)
--12394-- REDIR: 0x40184a0 (strlen) redirected to 0x4c2bec5 (strlen)
--12394-- Reading syms from /usr/lib/libregina-engine-4.6.1.so (0x4e31000)
--12394-- Reading syms from /usr/lib/libgmp.so.3.5.2 (0x52f7000)
--12394-- Reading debug info from /usr/lib/libgmp.so.3.5.2 ..
--12394-- .. CRC mismatch (computed d65050b9 wanted 1e40f6c0)
--12394-- object doesn't have a symbol table
--12394-- Reading syms from /lib/libpthread-2.11.1.so (0x5557000)
--12394-- Reading debug info from /lib/libpthread-2.11.1.so ..
--12394-- .. CRC mismatch (computed 9da7e2f6 wanted 8161fac5)
--12394-- Reading debug info from /usr/lib/debug/lib/libpthread-2.11.1.so ..
--12394-- Reading syms from /lib/librt-2.11.1.so (0x5774000)
--12394-- Reading debug info from /lib/librt-2.11.1.so ..
--12394-- .. CRC mismatch (computed 0e4f4ece wanted 920c9bed)
--12394-- Reading debug info from /usr/lib/debug/lib/librt-2.11.1.so ..
--12394-- Reading syms from /lib/libz.so.1.2.3.3 (0x597c000)
--12394-- Reading debug info from /lib/libz.so.1.2.3.3 ..
--12394-- .. CRC mismatch (computed 86f1fa27 wanted 5f1ca823)
--12394-- object doesn't have a symbol table
--12394-- Reading syms from /usr/lib/libstdc++.so.6.0.13 (0x5b93000)
--12394-- Reading debug info from /usr/lib/libstdc++.so.6.0.13 ..
--12394-- .. CRC mismatch (computed 7b5bd5a5 wanted e2f63673)
--12394-- object doesn't have a symbol table
--12394-- Reading syms from /lib/libm-2.11.1.so (0x5ea7000)
--12394-- Reading debug info from /lib/libm-2.11.1.so ..
--12394-- .. CRC mismatch (computed 043548c3 wanted a081b93d)
--12394-- Reading debug info from /usr/lib/debug/lib/libm-2.11.1.so ..
--12394-- Reading syms from /lib/libgcc_s.so.1 (0x612a000)
--12394-- Reading debug info from /lib/libgcc_s.so.1 ..
--12394-- .. CRC mismatch (computed 7c01dfc9 wanted 9d78e511)
--12394-- object doesn't have a symbol table
--12394-- Reading syms from /lib/libc-2.11.1.so (0x6341000)
--12394-- Reading debug info from /lib/libc-2.11.1.so ..
--12394-- .. CRC mismatch (computed c73d5a83 wanted 02758e3e)
--12394-- Reading debug info from /usr/lib/debug/lib/libc-2.11.1.so ..
--12394-- Reading syms from /usr/lib/libxml2.so.2.7.6 (0x66c4000)
--12394-- Reading debug info from /usr/lib/libxml2.so.2.7.6 ..
--12394-- .. CRC mismatch (computed c2590bed wanted 7aaa27a0)
--12394-- Reading debug info from /usr/lib/debug/usr/lib/libxml2.so.2.7.6 ..
--12394-- Reading syms from /lib/libdl-2.11.1.so (0x6a14000)
--12394-- Reading debug info from /lib/libdl-2.11.1.so ..
--12394-- .. CRC mismatch (computed 4a29f474 wanted e0b8d72c)
--12394-- Reading debug info from /usr/lib/debug/lib/libdl-2.11.1.so ..
--12394-- REDIR: 0x55603c0 (pthread_mutex_lock) redirected to 0x4c299fb (pthread_mutex_lock)
--12394-- REDIR: 0x5561a00 (pthread_mutex_unlock) redirected to 0x4c29e8c (pthread_mutex_unlock)
--12394-- REDIR: 0x63bd520 (malloc) redirected to 0x4c28a06 (malloc)
--12394-- REDIR: 0x63bf360 (calloc) redirected to 0x4c27cc9 (calloc)
--12394-- REDIR: 0x5c5e380 (operator new[](unsigned long)) redirected to 0x4c28e97 (operator new[](unsigned long))
--12394-- REDIR: 0x5c5e250 (operator new(unsigned long)) redirected to 0x4c2921f (operator new(unsigned long))
--12394-- REDIR: 0x5c5c380 (operator delete(void*)) redirected to 0x4c28328 (operator delete(void*))
--12394-- REDIR: 0x5c5c3c0 (operator delete[](void*)) redirected to 0x4c27fa4 (operator delete[](void*))
--12394-- REDIR: 0x63c3fe0 (strlen) redirected to 0x4a235dc (_vgnU_ifunc_wrapper)
--12394-- REDIR: 0x63c4010 (__GI_strlen) redirected to 0x4c2be91 (strlen)
--12394-- REDIR: 0x63c7c60 (memcpy) redirected to 0x4c2bfdb (memcpy)
Program will have 2 threads, working on 40 things
--12394-- REDIR: 0x555dd60 (pthread_create@@GLIBC_2.2.5) redirected to 0x4c2d4c7 (pthread_create@*)
==12394== Thread #2 was created
==12394== at 0x64276BE: clone (clone.S:77)
==12394== by 0x555E172: pthread_create@@GLIBC_2.2.5 (createthread.c:75)
==12394== by 0x4C2D42C: pthread_create_WRK (hg_intercepts.c:230)
==12394== by 0x4C2D4CF: pthread_create@* (hg_intercepts.c:257)
==12394== by 0x401C22: main (in /home/rybu/prog/regina/exercise/thread1)
==12394==
==12394== Thread #1 is the program's root thread
==12394==
==12394== Possible data race during write of size 8 at 0x7fefffcf0 by thread #2
==12394== at 0x4C2D54C: mythread_wrapper (hg_intercepts.c:200)
==12394== This conflicts with a previous read of size 8 by thread #1
==12394== at 0x4C2D440: pthread_create_WRK (hg_intercepts.c:235)
==12394== by 0x4C2D4CF: pthread_create@* (hg_intercepts.c:257)
==12394== by 0x401C22: main (in /home/rybu/prog/regina/exercise/thread1)
==12394==
started 21 completed 19 of 40==12394== Thread #3 was created
==12394== at 0x64276BE: clone (clone.S:77)
==12394== by 0x555E172: pthread_create@@GLIBC_2.2.5 (createthread.c:75)
==12394== by 0x4C2D42C: pthread_create_WRK (hg_intercepts.c:230)
==12394== by 0x4C2D4CF: pthread_create@* (hg_intercepts.c:257)
==12394== by 0x401C22: main (in /home/rybu/prog/regina/exercise/thread1)
==12394==
==12394== Possible data race during read of size 1 at 0x63401a7 by thread #3
==12394== at 0x613A4D7: ??? (in /lib/libgcc_s.so.1)
==12394== by 0x613A947: _Unwind_Resume (in /lib/libgcc_s.so.1)
==12394== by 0x4019C9: workerThread(void*) (in /home/rybu/prog/regina/exercise/thread1)
==12394== by 0x4C2D558: mythread_wrapper (hg_intercepts.c:202)
==12394== by 0x555D9C9: start_thread (pthread_create.c:300)
==12394== by 0x64276FC: clone (clone.S:112)
==12394== This conflicts with a previous write of size 1 by thread #2
==12394== at 0x6138331: ??? (in /lib/libgcc_s.so.1)
==12394== by 0x5563F42: pthread_once (pthread_once.S:104)
==12394== by 0x613A4C9: ??? (in /lib/libgcc_s.so.1)
==12394== by 0x613A7B6: _Unwind_ForcedUnwind (in /lib/libgcc_s.so.1)
==12394== by 0x556508F: __pthread_unwind (unwind.c:130)
==12394== by 0x555EEB4: pthread_exit (pthreadP.h:265)
==12394== by 0x40198E: workerThread(void*) (in /home/rybu/prog/regina/exercise/thread1)
==12394== by 0x4C2D558: mythread_wrapper (hg_intercepts.c:202)
==12394==
==12394== Possible data race during read of size 1 at 0x63401a6 by thread #3
==12394== at 0x6139A12: ??? (in /lib/libgcc_s.so.1)
==12394== by 0x6139AA8: ??? (in /lib/libgcc_s.so.1)
==12394== by 0x613A724: ??? (in /lib/libgcc_s.so.1)
==12394== by 0x613A982: _Unwind_Resume (in /lib/libgcc_s.so.1)
==12394== by 0x4019C9: workerThread(void*) (in /home/rybu/prog/regina/exercise/thread1)
==12394== by 0x4C2D558: mythread_wrapper (hg_intercepts.c:202)
==12394== by 0x555D9C9: start_thread (pthread_create.c:300)
==12394== by 0x64276FC: clone (clone.S:112)
==12394== This conflicts with a previous write of size 1 by thread #2
==12394== at 0x613832A: ??? (in /lib/libgcc_s.so.1)
==12394== by 0x5563F42: pthread_once (pthread_once.S:104)
==12394== by 0x613A4C9: ??? (in /lib/libgcc_s.so.1)
==12394== by 0x613A7B6: _Unwind_ForcedUnwind (in /lib/libgcc_s.so.1)
==12394== by 0x556508F: __pthread_unwind (unwind.c:130)
==12394== by 0x555EEB4: pthread_exit (pthreadP.h:265)
==12394== by 0x40198E: workerThread(void*) (in /home/rybu/prog/regina/exercise/thread1)
==12394== by 0x4C2D558: mythread_wrapper (hg_intercepts.c:202)
==12394==
==12394== Possible data race during read of size 1 at 0x63401b0 by thread #3
==12394== at 0x6139AD7: ??? (in /lib/libgcc_s.so.1)
==12394== by 0x613A724: ??? (in /lib/libgcc_s.so.1)
==12394== by 0x613A982: _Unwind_Resume (in /lib/libgcc_s.so.1)
==12394== by 0x4019C9: workerThread(void*) (in /home/rybu/prog/regina/exercise/thread1)
==12394== by 0x4C2D558: mythread_wrapper (hg_intercepts.c:202)
==12394== by 0x555D9C9: start_thread (pthread_create.c:300)
==12394== by 0x64276FC: clone (clone.S:112)
==12394== This conflicts with a previous write of size 1 by thread #2
==12394== at 0x6138370: ??? (in /lib/libgcc_s.so.1)
==12394== by 0x5563F42: pthread_once (pthread_once.S:104)
==12394== by 0x613A4C9: ??? (in /lib/libgcc_s.so.1)
==12394== by 0x613A7B6: _Unwind_ForcedUnwind (in /lib/libgcc_s.so.1)
==12394== by 0x556508F: __pthread_unwind (unwind.c:130)
==12394== by 0x555EEB4: pthread_exit (pthreadP.h:265)
==12394== by 0x40198E: workerThread(void*) (in /home/rybu/prog/regina/exercise/thread1)
==12394== by 0x4C2D558: mythread_wrapper (hg_intercepts.c:202)
==12394==
--12394-- REDIR: 0x63bede0 (free) redirected to 0x4c28616 (free)
started 40 completed 40 of 40--12394-- REDIR: 0x555ef30 (pthread_join) redirected to 0x4c29796 (pthread_join)
thread 0 worked on task 0
thread 1 worked on task 1
thread 0 worked on task 2
thread 1 worked on task 3
thread 0 worked on task 4
thread 1 worked on task 5
thread 0 worked on task 6
thread 1 worked on task 7
thread 0 worked on task 8
thread 1 worked on task 9
thread 0 worked on task 10
thread 1 worked on task 11
thread 0 worked on task 12
thread 1 worked on task 13
thread 0 worked on task 14
thread 1 worked on task 15
thread 0 worked on task 16
thread 1 worked on task 17
thread 0 worked on task 18
thread 1 worked on task 19
thread 0 worked on task 20
thread 1 worked on task 21
thread 0 worked on task 22
thread 1 worked on task 23
thread 0 worked on task 24
thread 1 worked on task 25
thread 0 worked on task 26
thread 1 worked on task 27
thread 0 worked on task 28
thread 1 worked on task 29
thread 0 worked on task 30
thread 1 worked on task 31
thread 0 worked on task 32
thread 1 worked on task 33
thread 0 worked on task 34
thread 1 worked on task 35
thread 0 worked on task 36
thread 1 worked on task 37
thread 0 worked on task 38
thread 1 worked on task 39
==12394==
==12394== ERROR SUMMARY: 7 errors from 4 contexts (suppressed: 804 from 64)
==12394==
==12394== 1 errors in context 1 of 4:
==12394== Possible data race during read of size 1 at 0x63401a7 by thread #3
==12394== at 0x613A4D7: ??? (in /lib/libgcc_s.so.1)
==12394== by 0x613A947: _Unwind_Resume (in /lib/libgcc_s.so.1)
==12394== by 0x4019C9: workerThread(void*) (in /home/rybu/prog/regina/exercise/thread1)
==12394== by 0x4C2D558: mythread_wrapper (hg_intercepts.c:202)
==12394== by 0x555D9C9: start_thread (pthread_create.c:300)
==12394== by 0x64276FC: clone (clone.S:112)
==12394== This conflicts with a previous write of size 1 by thread #2
==12394== at 0x6138331: ??? (in /lib/libgcc_s.so.1)
==12394== by 0x5563F42: pthread_once (pthread_once.S:104)
==12394== by 0x613A4C9: ??? (in /lib/libgcc_s.so.1)
==12394== by 0x613A7B6: _Unwind_ForcedUnwind (in /lib/libgcc_s.so.1)
==12394== by 0x556508F: __pthread_unwind (unwind.c:130)
==12394== by 0x555EEB4: pthread_exit (pthreadP.h:265)
==12394== by 0x40198E: workerThread(void*) (in /home/rybu/prog/regina/exercise/thread1)
==12394== by 0x4C2D558: mythread_wrapper (hg_intercepts.c:202)
==12394==
==12394==
==12394== 2 errors in context 2 of 4:
==12394== Possible data race during read of size 1 at 0x63401b0 by thread #3
==12394== at 0x6139AD7: ??? (in /lib/libgcc_s.so.1)
==12394== by 0x613A724: ??? (in /lib/libgcc_s.so.1)
==12394== by 0x613A982: _Unwind_Resume (in /lib/libgcc_s.so.1)
==12394== by 0x4019C9: workerThread(void*) (in /home/rybu/prog/regina/exercise/thread1)
==12394== by 0x4C2D558: mythread_wrapper (hg_intercepts.c:202)
==12394== by 0x555D9C9: start_thread (pthread_create.c:300)
==12394== by 0x64276FC: clone (clone.S:112)
==12394== This conflicts with a previous write of size 1 by thread #2
==12394== at 0x6138370: ??? (in /lib/libgcc_s.so.1)
==12394== by 0x5563F42: pthread_once (pthread_once.S:104)
==12394== by 0x613A4C9: ??? (in /lib/libgcc_s.so.1)
==12394== by 0x613A7B6: _Unwind_ForcedUnwind (in /lib/libgcc_s.so.1)
==12394== by 0x556508F: __pthread_unwind (unwind.c:130)
==12394== by 0x555EEB4: pthread_exit (pthreadP.h:265)
==12394== by 0x40198E: workerThread(void*) (in /home/rybu/prog/regina/exercise/thread1)
==12394== by 0x4C2D558: mythread_wrapper (hg_intercepts.c:202)
==12394==
==12394==
==12394== 2 errors in context 3 of 4:
==12394== Possible data race during read of size 1 at 0x63401a6 by thread #3
==12394== at 0x6139A12: ??? (in /lib/libgcc_s.so.1)
==12394== by 0x6139AA8: ??? (in /lib/libgcc_s.so.1)
==12394== by 0x613A724: ??? (in /lib/libgcc_s.so.1)
==12394== by 0x613A982: _Unwind_Resume (in /lib/libgcc_s.so.1)
==12394== by 0x4019C9: workerThread(void*) (in /home/rybu/prog/regina/exercise/thread1)
==12394== by 0x4C2D558: mythread_wrapper (hg_intercepts.c:202)
==12394== by 0x555D9C9: start_thread (pthread_create.c:300)
==12394== by 0x64276FC: clone (clone.S:112)
==12394== This conflicts with a previous write of size 1 by thread #2
==12394== at 0x613832A: ??? (in /lib/libgcc_s.so.1)
==12394== by 0x5563F42: pthread_once (pthread_once.S:104)
==12394== by 0x613A4C9: ??? (in /lib/libgcc_s.so.1)
==12394== by 0x613A7B6: _Unwind_ForcedUnwind (in /lib/libgcc_s.so.1)
==12394== by 0x556508F: __pthread_unwind (unwind.c:130)
==12394== by 0x555EEB4: pthread_exit (pthreadP.h:265)
==12394== by 0x40198E: workerThread(void*) (in /home/rybu/prog/regina/exercise/thread1)
==12394== by 0x4C2D558: mythread_wrapper (hg_intercepts.c:202)
==12394==
==12394==
==12394== 2 errors in context 4 of 4:
==12394== Possible data race during write of size 8 at 0x7fefffcf0 by thread #2
==12394== at 0x4C2D54C: mythread_wrapper (hg_intercepts.c:200)
==12394== This conflicts with a previous read of size 8 by thread #1
==12394== at 0x4C2D440: pthread_create_WRK (hg_intercepts.c:235)
==12394== by 0x4C2D4CF: pthread_create@* (hg_intercepts.c:257)
==12394== by 0x401C22: main (in /home/rybu/prog/regina/exercise/thread1)
==12394==
--12394--
--12394-- used_suppression: 610 helgrind-glibc2X-101
--12394-- used_suppression: 192 helgrind---...-*Unwind*-*pthread_unwind*
--12394-- used_suppression: 2 helgrind-glibc2X-112
==12394==
==12394== ERROR SUMMARY: 7 errors from 4 contexts (suppressed: 804 from 64)
I'm not so confident when it comes to interpreting helgrind output.
Thanks for any insights.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
您正在使用繁忙循环:
查找条件变量。
这样,您的线程就不会消耗等待工作出现在队列中的资源。
查看此问题
您标记了问题 C++ 但您正在使用C 风格转换。
另请注意,在 C++ 中,您不需要在此处添加结构。
从技术上讲,您应该声明您的回调函数以使用 C ABI(因为这是一个 C 库。
个人选择将 * 移到类型旁边(但这只是我个人的偏好)。
您没有使用 RAII。所以您的锁定/解锁场景 也不是异常安全的。通过创建锁对象来使其安全。
即使中间的东西现在不能抛出,
You are using a busy loop:
look up condition variable.
That way your thread is not consuming resources waiting for work to appear in the queue.
See this question
You tagged the question C++ but you are using C style casts.
Also note that in C++ you do not need to add struct here.
Technically you should declare your callback function to use the C ABI (as this is a C library.
Personal choice move the * beside the type (but that is just my personal pref).
You are not using RAII. So your lock/unlock senarios are not exception safe.
Even if stuff in the middle can not throw now. You are assuming that somebody will not add code that that does not throw in the future. Make it safe by creating a lock object.
我至少缺少线程函数的 extern "C" {} 块,因为 C 库需要 C ABI。除此之外,我看不到任何明显的东西。
例如创建一个原型,如下所示:
I'm missing an extern "C" {} block for your thread function at least, since a C library would expect a C ABI. Other than that, I can't see anything obvious.
E.g. create a prototype like:
您的一些错误来自
libgcc_s.so
。其中一些似乎发生在线程初始化期间,甚至在调用函数之前。尝试使用
gcc -pthread
进行编译,以确保编译器知道发生了什么。Several of your errors come from
libgcc_s.so
. Some of them appear to occur during thread initialization, before your function is even called.Try compiling with
gcc -pthread
to make sure the compiler knows what's going on.这实际上取决于您的编译器。在 gnu 和 clang 中,您不需要在函数调用周围使用 extern c 。虽然我在一些编译器中听说过你这样做。
That actually depends on your compiler. In both gnu and clang you dont need the extern c around the function call. Though I have heard in some compilers you do.