Skip to content

Commit e94679a

Browse files
committed
adding per-thread stack size control
1 parent 393d80b commit e94679a

File tree

3 files changed

+79
-27
lines changed

3 files changed

+79
-27
lines changed

gclib/GThreads.cpp

Lines changed: 43 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ freely, subject to the following restrictions:
2929
#elif defined(_GTHREADS_WIN32_)
3030
#include <process.h>
3131
#endif
32-
32+
#include <string.h>
3333

3434
//namespace tthread {
3535

@@ -146,6 +146,16 @@ static thread::id _pthread_t_to_ID(const pthread_t &aHandle)
146146
#endif // _GTHREADS_POSIX_
147147
*/
148148

149+
void gthreads_errExit(int err, const char* msg) {
150+
if (msg!=NULL)
151+
fprintf(stderr, "GThreads Error: %s (%s)\n", msg, strerror(err));
152+
else
153+
fprintf(stderr, "GThreads Error: %s\n", strerror(err));
154+
exit(EXIT_FAILURE);
155+
}
156+
157+
158+
149159
void GThread::update_counter(int inc, GThread* t_update) {
150160
static GMutex counterLock;
151161
GLockGuard<GMutex> guard(counterLock);
@@ -158,7 +168,7 @@ void GThread::update_counter(int inc, GThread* t_update) {
158168
t_update->mId=0; // thread terminated
159169

160170
}
161-
171+
162172

163173
//------------------------------------------------------------------------------
164174
// thread
@@ -240,7 +250,7 @@ void * GThread::wrapper_function(void * aArg)
240250
}
241251

242252

243-
void GThread::initStart(void* tidata) {
253+
void GThread::initStart(void* tidata, size_t stacksize) {
244254
_thread_start_info * ti = (_thread_start_info *) tidata;
245255
/*ti->mFunction = aFunction;
246256
ti->mArg = aArg;
@@ -253,10 +263,29 @@ void GThread::initStart(void* tidata) {
253263
#if defined(_GTHREADS_WIN32_)
254264
mHandle = (HANDLE) _beginthreadex(0, 0, wrapper_function, (void *) ti, 0, &mWin32ThreadID);
255265
#elif defined(_GTHREADS_POSIX_)
256-
if(pthread_create(&mHandle, NULL, wrapper_function, (void *) ti) != 0)
257-
mHandle = 0;
258-
#endif
266+
if (stacksize>0) {
267+
pthread_attr_t attr;
268+
int r=pthread_attr_init(&attr);
269+
if (r!=0) gthreads_errExit(r, "pthread_attr_init()");
270+
r = pthread_attr_setstacksize(&attr, stacksize);
271+
if (r!=0) gthreads_errExit(r, "pthread_attr_setstacksize()");
272+
stack_size=stacksize;
273+
r=pthread_create(&mHandle, &attr, wrapper_function, (void *) ti);
274+
if (r!=0) {
275+
gthreads_errExit(r, "pthread_create()");
276+
//mHandle = 0;
277+
}
278+
r=pthread_attr_destroy(&attr);
279+
if (r!=0) gthreads_errExit(r, "pthread_attr_destroy()");
280+
}
281+
else {
282+
int r=pthread_create(&mHandle, NULL, wrapper_function, (void *) ti);
283+
if (r!= 0)
284+
gthreads_errExit(r, "pthread_create()");
285+
//mHandle = 0;
286+
}
259287

288+
#endif
260289
// Did we fail to create the thread?
261290
if(!mHandle)
262291
{
@@ -266,39 +295,38 @@ void GThread::initStart(void* tidata) {
266295
else GThread::update_counter(1, this);
267296
}
268297

269-
//GThread::GThread(void (*aFunction)(void *, GThread*), void * aArg)
270-
GThread::GThread(void (*aFunction)(void *), void * aArg): mId(0), mHandle(0), mNotAThread(true)
298+
GThread::GThread(void (*aFunction)(void *), void * aArg, size_t stacksize): mId(0), mHandle(0), mNotAThread(true)
271299
#if defined(_GTHREADS_WIN32_)
272300
, mWin32ThreadID(0)
273301
#endif
274302
{
275-
kickStart(aFunction, aArg);
303+
kickStart(aFunction, aArg, stacksize);
276304
}
277305

278-
void GThread::kickStart(void (*aFunction)(void *), void * aArg) {
306+
void GThread::kickStart(void (*aFunction)(void *), void * aArg, size_t stacksize) {
279307
// Serialize access to this thread structure
280308
GLockGuard<GMutex> guard(mDataMutex);
281309
// Fill out the thread startup information (passed to the thread wrapper,
282310
// which will eventually free it)
283311
_thread_start_info * ti = new _thread_start_info(this, aFunction, aArg);
284-
initStart(ti);
312+
initStart(ti, stacksize);
285313
}
286314

287315
//custom alternate constructor (non-C++11 compatible), passing GThreadData back to the
288316
//user function in order to easily retrieve current GThread object
289317
//(better alternative to this_thread)
290-
GThread::GThread(void (*gFunction)(GThreadData& thread_data), void * aArg) {
291-
kickStart(gFunction, aArg);
318+
GThread::GThread(void (*gFunction)(GThreadData& thread_data), void * aArg, size_t stacksize) {
319+
kickStart(gFunction, aArg, stacksize);
292320
}
293321

294-
void GThread::kickStart(void (*gFunction)(GThreadData& thread_data), void * aArg) {
322+
void GThread::kickStart(void (*gFunction)(GThreadData& thread_data), void * aArg, size_t stacksize) {
295323
// Serialize access to this thread structure
296324
GLockGuard<GMutex> guard(mDataMutex);
297325

298326
// Fill out the thread startup information (passed to the thread wrapper,
299327
// which will eventually free it)
300328
_thread_start_info * ti = new _thread_start_info(this, gFunction, aArg);
301-
initStart(ti);
329+
initStart(ti, stacksize);
302330
}
303331

304332
GThread::~GThread()

gclib/GThreads.h

Lines changed: 23 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -101,9 +101,9 @@ freely, subject to the following restrictions:
101101
#include <sched.h>
102102
#include <unistd.h>
103103
#endif
104-
105-
// Generic includes
106-
//#include <ostream>
104+
#include <stdlib.h>
105+
#include <stdio.h>
106+
#include <errno.h>
107107

108108
/// TinyThread++ version (major number).
109109
#define TINYTHREAD_VERSION_MAJOR 1
@@ -174,6 +174,10 @@ freely, subject to the following restrictions:
174174
/// the std::mutex class.
175175
//namespace tthread {
176176

177+
void gthreads_errExit(int err, const char* msg=NULL);
178+
179+
#define pthreads_err(msg) \
180+
do { perror(msg); exit(EXIT_FAILURE); } while (0)
177181
/// GMutex class
178182
/// This is a mutual exclusion object for synchronizing access to shared
179183
/// memory areas for several threads. The mutex is non-recursive (i.e. a
@@ -696,6 +700,7 @@ class GThread {
696700
#endif
697701
private:
698702
int mId;
703+
size_t stack_size; //available only for pthreads
699704
static int tcounter; //counts live, joinable GThread instances
700705
static int num_created; //counts all joinable GThread instances ever created by current process
701706

@@ -709,7 +714,7 @@ class GThread {
709714
/// Default constructor.
710715
/// Construct a thread object without an associated thread of execution
711716
/// (i.e. non-joinable).
712-
GThread() : mId(0), mHandle(0), mNotAThread(true)
717+
GThread(size_t stacksize=0) : mId(0), stack_size(stacksize), mHandle(0), mNotAThread(true)
713718
#if defined(_GTHREADS_WIN32_)
714719
, mWin32ThreadID(0)
715720
#endif
@@ -724,12 +729,12 @@ class GThread {
724729
/// thread class. It is more similar to the pthread_create() (POSIX) and
725730
/// CreateThread() (Windows) functions.
726731
//GThread(void (*aFunction)(void *, GThread*), void * aArg);
727-
GThread(void (*aFunction)(void *), void * aArg=NULL);
732+
GThread(void (*aFunction)(void *), void * aArg=NULL, size_t stacksize=0);
728733

729-
GThread(void (*aFunction)(GThreadData& thread_data), void * aArg);
734+
GThread(void (*aFunction)(GThreadData& thread_data), void * aArg, size_t stacksize=0);
730735

731-
void kickStart(void (*aFunction)(GThreadData& thread_data), void * aArg);
732-
void kickStart(void (*aFunction)(void *), void * aArg=NULL);
736+
void kickStart(void (*aFunction)(GThreadData& thread_data), void * aArg, size_t stacksize=0);
737+
void kickStart(void (*aFunction)(void *), void * aArg=NULL, size_t stacksize=0);
733738

734739
/// Destructor.
735740
/// @note If the thread is joinable upon destruction, \c std::terminate()
@@ -752,7 +757,7 @@ class GThread {
752757
void detach();
753758
/// Return the thread ID of a thread object.
754759
int get_id() const; // { return mID; }
755-
760+
size_t getStackSize() { return stack_size; } //only for pthreads
756761
/// Get the native handle for this thread.
757762
/// @note Under Windows, this is a \c HANDLE, and under POSIX systems, this
758763
/// is a \c pthread_t.
@@ -775,6 +780,14 @@ class GThread {
775780
int r=tcounter;
776781
return r;
777782
}
783+
static size_t defaultStackSize() {
784+
pthread_attr_t attr;
785+
size_t stacksize;
786+
pthread_attr_init(&attr);
787+
pthread_attr_getstacksize(&attr, &stacksize);
788+
pthread_attr_destroy(&attr);
789+
return stacksize;
790+
}
778791
static int liveCount() {
779792
//return number of running (live) threads
780793
return num_running();
@@ -790,7 +803,7 @@ class GThread {
790803
_GTHREADS_DISABLE_ASSIGNMENT(GThread)
791804

792805
private:
793-
void initStart(void* tidata);
806+
void initStart(void* tidata, size_t stacksize=0);
794807
static void update_counter(int inc=1, GThread* t_update=NULL); //default: increments
795808
// This is the internal thread wrapper function.
796809
#if defined(_GTHREADS_WIN32_)

stringtie.cpp

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -385,6 +385,17 @@ const char* ERR_BAM_SORT="\nError: the input alignment file is not sorted!\n";
385385
if (ballgown)
386386
Ballgown_setupFiles(f_tdata, f_edata, f_idata, f_e2t, f_i2t);
387387
#ifndef NOTHREADS
388+
#define DEF_TSTACK_SIZE 8388608
389+
int tstackSize=GThread::defaultStackSize();
390+
size_t defStackSize=0;
391+
if (tstackSize<DEF_TSTACK_SIZE) defStackSize=DEF_TSTACK_SIZE;
392+
if (verbose) {
393+
if (defStackSize>0){
394+
int ssize=defStackSize;
395+
GMessage("Default stack size for threads: %d (increased to %d)\n", tstackSize, ssize);
396+
}
397+
else GMessage("Default stack size for threads: %d\n", tstackSize);
398+
}
388399
GThread* threads=new GThread[num_cpus]; //bundle processing threads
389400

390401
GPVec<BundleData> bundleQueue(false); //queue of loaded bundles
@@ -394,7 +405,7 @@ if (ballgown)
394405

395406
dataClear.setCapacity(num_cpus+1);
396407
for (int b=0;b<num_cpus;b++) {
397-
threads[b].kickStart(workerThread, (void*) &bundleQueue);
408+
threads[b].kickStart(workerThread, (void*) &bundleQueue, defStackSize);
398409
bundles[b+1].idx=b+1;
399410
dataClear.Push(b);
400411
}
@@ -1230,8 +1241,8 @@ void processBundle(BundleData* bundle) {
12301241
NumFrag3+=bundle->num_fragments3;
12311242
SumFrag3+=bundle->sum_fragments3;
12321243
fprintf(stderr,"Number of fragments in bundle: %g with length %g\n",bundle->num_fragments,bundle->frag_len);
1233-
*/
12341244
fprintf(stderr,"Number of fragments in bundle: %g with sum %g\n",bundle->num_fragments,bundle->frag_len);
1245+
*/
12351246
GMessage("^bundle %s:%d-%d(%d) done (%d processed potential transcripts).\n",bundle->refseq.chars(),
12361247
bundle->start, bundle->end, bundle->readlist.Count(), bundle->pred.Count());
12371248
#ifdef GMEMTRACE

0 commit comments

Comments
 (0)