Bug 664341 - Provide API to specify thread stack size. r=bsmedberg
authorChris Pearce <chris@pearce.org.nz>
Wed, 27 Jul 2011 15:26:47 +1200
changeset 73408 c56067ea79887064167c21a7110b2becefe5be45
parent 73407 b6937b8ba51ba950a45c767cef0245f4bb8cfff1
child 73409 685b3762558c91d19580dc295e54c43a7138f911
push id20859
push usermak77@bonardo.net
push dateWed, 27 Jul 2011 10:12:57 +0000
treeherdermozilla-central@e4c8a1e7b373 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbsmedberg
bugs664341
milestone8.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 664341 - Provide API to specify thread stack size. r=bsmedberg
xpcom/glue/nsThreadUtils.cpp
xpcom/glue/nsThreadUtils.h
xpcom/threads/nsIThreadManager.idl
xpcom/threads/nsThread.cpp
xpcom/threads/nsThread.h
xpcom/threads/nsThreadManager.cpp
xpcom/threads/nsThreadPool.cpp
--- a/xpcom/glue/nsThreadUtils.cpp
+++ b/xpcom/glue/nsThreadUtils.cpp
@@ -61,29 +61,29 @@ nsRunnable::Run()
   return NS_OK;
 }
 
 #endif  // XPCOM_GLUE_AVOID_NSPR
 
 //-----------------------------------------------------------------------------
 
 NS_METHOD
-NS_NewThread(nsIThread **result, nsIRunnable *event)
+NS_NewThread(nsIThread **result, nsIRunnable *event, PRUint32 stackSize)
 {
   nsCOMPtr<nsIThread> thread;
 #ifdef MOZILLA_INTERNAL_API
   nsresult rv = nsThreadManager::get()->
-      nsThreadManager::NewThread(0, getter_AddRefs(thread));
+      nsThreadManager::NewThread(0, stackSize, getter_AddRefs(thread));
 #else
   nsresult rv;
   nsCOMPtr<nsIThreadManager> mgr =
       do_GetService(NS_THREADMANAGER_CONTRACTID, &rv);
   NS_ENSURE_SUCCESS(rv, rv);
 
-  rv = mgr->NewThread(0, getter_AddRefs(thread));
+  rv = mgr->NewThread(0, stackSize, getter_AddRefs(thread));
 #endif
   NS_ENSURE_SUCCESS(rv, rv);
 
   if (event) {
     rv = thread->Dispatch(event, NS_DISPATCH_NORMAL);
     NS_ENSURE_SUCCESS(rv, rv);
   }
 
--- a/xpcom/glue/nsThreadUtils.h
+++ b/xpcom/glue/nsThreadUtils.h
@@ -70,22 +70,26 @@
 
 /**
  * Create a new thread, and optionally provide an initial event for the thread.
  *
  * @param result
  *   The resulting nsIThread object.
  * @param initialEvent
  *   The initial event to run on this thread.  This parameter may be null.
+ * @param stackSize
+ *   The size in bytes to reserve for the thread's stack.
  *
  * @returns NS_ERROR_INVALID_ARG
  *   Indicates that the given name is not unique.
  */
 extern NS_COM_GLUE NS_METHOD
-NS_NewThread(nsIThread **result, nsIRunnable *initialEvent = nsnull);
+NS_NewThread(nsIThread **result,
+             nsIRunnable *initialEvent = nsnull,
+             PRUint32 stackSize = nsIThreadManager::DEFAULT_STACK_SIZE);
 
 /**
  * Get a reference to the current thread.
  *
  * @param result
  *   The resulting nsIThread object.
  */
 extern NS_COM_GLUE NS_METHOD
--- a/xpcom/threads/nsIThreadManager.idl
+++ b/xpcom/threads/nsIThreadManager.idl
@@ -40,30 +40,38 @@
 
 [ptr] native PRThread(PRThread);
 
 interface nsIThread;
 
 /**
  * An interface for creating and locating nsIThread instances.
  */
-[scriptable, uuid(487c10bf-0a22-4148-89fa-790d819dd559)]
+[scriptable, uuid(2bbbc38c-cf96-4099-ba6b-f6a44d8b014c)]
 interface nsIThreadManager : nsISupports
 {
   /**
+   * Default number of bytes reserved for a thread's stack, if no stack size
+   * is specified in newThread(). 0 means use platform default.
+   */
+  const unsigned long DEFAULT_STACK_SIZE = 0;
+
+  /**
    * Create a new thread (a global, user PRThread).
    *
    * @param creationFlags
    *   Reserved for future use.  Pass 0.
+   * @param stackSize
+   *   Number of bytes to reserve for the thread's stack.
    *
    * @returns
    *   The newly created nsIThread object.
    */
-  nsIThread newThread(in unsigned long creationFlags);
-   
+  nsIThread newThread(in unsigned long creationFlags, [optional] in unsigned long stackSize);
+
   /**
    * Get the nsIThread object (if any) corresponding to the given PRThread.
    * This method returns null if there is no corresponding nsIThread.
    *
    * @param prthread
    *   The PRThread of the nsIThread being requested.
    *
    * @returns
--- a/xpcom/threads/nsThread.cpp
+++ b/xpcom/threads/nsThread.cpp
@@ -307,16 +307,30 @@ nsThread::ThreadFunc(void *arg)
 //-----------------------------------------------------------------------------
 
 nsThread::nsThread()
   : mLock("nsThread.mLock")
   , mEvents(&mEventsRoot)
   , mPriority(PRIORITY_NORMAL)
   , mThread(nsnull)
   , mRunningEvent(0)
+  , mStackSize(0)
+  , mShutdownContext(nsnull)
+  , mShutdownRequired(PR_FALSE)
+  , mEventsAreDoomed(PR_FALSE)
+{
+}
+
+nsThread::nsThread(PRUint32 aStackSize)
+  : mLock("nsThread.mLock")
+  , mEvents(&mEventsRoot)
+  , mPriority(PRIORITY_NORMAL)
+  , mThread(nsnull)
+  , mRunningEvent(0)
+  , mStackSize(aStackSize)
   , mShutdownContext(nsnull)
   , mShutdownRequired(PR_FALSE)
   , mEventsAreDoomed(PR_FALSE)
 {
 }
 
 nsThread::~nsThread()
 {
@@ -331,17 +345,17 @@ nsThread::Init()
  
   NS_ADDREF_THIS();
  
   mShutdownRequired = PR_TRUE;
 
   // ThreadFunc is responsible for setting mThread
   PRThread *thr = PR_CreateThread(PR_USER_THREAD, ThreadFunc, this,
                                   PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD,
-                                  PR_JOINABLE_THREAD, 0);
+                                  PR_JOINABLE_THREAD, mStackSize);
   if (!thr) {
     NS_RELEASE_THIS();
     return NS_ERROR_OUT_OF_MEMORY;
   }
 
   // ThreadFunc will wait for this event to be run before it tries to access
   // mThread.  By delaying insertion of this event into the queue, we ensure
   // that mThread is set properly.
--- a/xpcom/threads/nsThread.h
+++ b/xpcom/threads/nsThread.h
@@ -53,16 +53,17 @@ class nsThread : public nsIThreadInterna
 public:
   NS_DECL_ISUPPORTS
   NS_DECL_NSIEVENTTARGET
   NS_DECL_NSITHREAD
   NS_DECL_NSITHREADINTERNAL
   NS_DECL_NSISUPPORTSPRIORITY
 
   nsThread();
+  nsThread(PRUint32 aStackSize);
 
   // Initialize this as a wrapper for a new PRThread.
   nsresult Init();
 
   // Initialize this as a wrapper for the current PRThread.
   nsresult InitCurrentThread();
 
   // The PRThread corresponding to this thread.
@@ -133,16 +134,17 @@ private:
   nsAutoTObserverArray<nsCOMPtr<nsIThreadObserver>, 2> mEventObservers;
 
   nsChainedEventQueue *mEvents;   // never null
   nsChainedEventQueue  mEventsRoot;
 
   PRInt32   mPriority;
   PRThread *mThread;
   PRUint32  mRunningEvent;  // counter
+  PRUint32  mStackSize;
 
   struct nsThreadShutdownContext *mShutdownContext;
 
   PRPackedBool mShutdownRequired;
   PRPackedBool mShutdownPending;
   // Set to true when events posted to this thread will never run.
   PRPackedBool mEventsAreDoomed;
 };
--- a/xpcom/threads/nsThreadManager.cpp
+++ b/xpcom/threads/nsThreadManager.cpp
@@ -227,22 +227,24 @@ nsThreadManager::GetCurrentThread()
   nsRefPtr<nsThread> thread = new nsThread();
   if (!thread || NS_FAILED(thread->InitCurrentThread()))
     return nsnull;
 
   return thread.get();  // reference held in TLS
 }
 
 NS_IMETHODIMP
-nsThreadManager::NewThread(PRUint32 creationFlags, nsIThread **result)
+nsThreadManager::NewThread(PRUint32 creationFlags,
+                           PRUint32 stackSize,
+                           nsIThread **result)
 {
   // No new threads during Shutdown
   NS_ENSURE_TRUE(mInitialized, NS_ERROR_NOT_INITIALIZED);
 
-  nsThread *thr = new nsThread();
+  nsThread *thr = new nsThread(stackSize);
   if (!thr)
     return NS_ERROR_OUT_OF_MEMORY;
   NS_ADDREF(thr);
 
   nsresult rv = thr->Init();
   if (NS_FAILED(rv)) {
     NS_RELEASE(thr);
     return rv;
--- a/xpcom/threads/nsThreadPool.cpp
+++ b/xpcom/threads/nsThreadPool.cpp
@@ -105,17 +105,19 @@ nsThreadPool::PutEvent(nsIRunnable *even
     mEvents.PutEvent(event);
   }
 
   LOG(("THRD-P(%p) put [spawn=%d]\n", this, spawnThread));
   if (!spawnThread)
     return NS_OK;
 
   nsCOMPtr<nsIThread> thread;
-  nsThreadManager::get()->NewThread(0, getter_AddRefs(thread));
+  nsThreadManager::get()->NewThread(0,
+                                    nsIThreadManager::DEFAULT_STACK_SIZE,
+                                    getter_AddRefs(thread));
   NS_ENSURE_STATE(thread);
 
   PRBool killThread = PR_FALSE;
   {
     ReentrantMonitorAutoEnter mon(mEvents.GetReentrantMonitor());
     if (mThreads.Count() < (PRInt32) mThreadLimit) {
       mThreads.AppendObject(thread);
     } else {