VirtualBox

Changeset 103488 in vbox


Ignore:
Timestamp:
Feb 21, 2024 10:55:12 AM (9 months ago)
Author:
vboxsync
Message:

libs/xpcom: Remove the old multithread code because testboxes appear to be happy with the IPRT thread pool approach, bugref:5973

Location:
trunk/src/libs/xpcom18a4/ipc/ipcd/extensions/dconnect/src
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/libs/xpcom18a4/ipc/ipcd/extensions/dconnect/src/ipcDConnectService.cpp

    r103476 r103488  
    6464#endif /* VBOX */
    6565
    66 #if defined(DCONNECT_MULTITHREADED)
    67 
    68 #if !defined(DCONNECT_WITH_IPRT_REQ_POOL)
    69 #include "nsIRunnable.h"
    70 #endif
    71 
    7266#if defined(DEBUG) && !defined(DCONNECT_STATS)
    7367#define DCONNECT_STATS
     
    7670#if defined(DCONNECT_STATS)
    7771#include <stdio.h>
    78 #endif
    79 
    8072#endif
    8173
     
    28812873//-----------------------------------------------------------------------------
    28822874
    2883 #if defined(DCONNECT_MULTITHREADED)  && !defined(DCONNECT_WITH_IPRT_REQ_POOL)
    2884 
    2885 class DConnectWorker : public nsIRunnable
    2886 {
    2887 public:
    2888   // no reference counting
    2889   NS_IMETHOD_(nsrefcnt) AddRef() { return 1; }
    2890   NS_IMETHOD_(nsrefcnt) Release() { return 1; }
    2891   NS_IMETHOD QueryInterface(const nsIID &aIID, void **aInstancePtr);
    2892 
    2893   NS_DECL_NSIRUNNABLE
    2894 
    2895   DConnectWorker(ipcDConnectService *aDConnect) : mDConnect (aDConnect), mIsRunnable (PR_FALSE) {}
    2896   NS_HIDDEN_(nsresult) Init();
    2897   NS_HIDDEN_(void) Join()
    2898   {
    2899     int rcThread;
    2900     int vrc = RTThreadWait(mThread, RT_INDEFINITE_WAIT, &rcThread);
    2901     AssertRC(vrc); RT_NOREF(vrc);
    2902     AssertRC(rcThread);
    2903   };
    2904   NS_HIDDEN_(bool) IsRunning() { return mIsRunnable; };
    2905 
    2906 private:
    2907 
    2908   static DECLCALLBACK(int) dconnectWorkerRun(RTTHREAD hSelf, void *pvUser);
    2909 
    2910   RTTHREAD           mThread;
    2911   ipcDConnectService *mDConnect;
    2912 
    2913   // Indicate if thread might be quickly joined on shutdown.
    2914   volatile bool mIsRunnable;
    2915 };
    2916 
    2917 NS_IMPL_QUERY_INTERFACE1(DConnectWorker, nsIRunnable)
    2918 
    2919 /*static*/
    2920 DECLCALLBACK(int) DConnectWorker::dconnectWorkerRun(RTTHREAD hSelf, void *pvUser)
    2921 {
    2922   DConnectWorker *pThis = (DConnectWorker *)pvUser;
    2923   pThis->Run();
    2924   return VINF_SUCCESS;
    2925 }
    2926 
    2927 
    2928 nsresult
    2929 DConnectWorker::Init()
    2930 {
    2931   int vrc = RTThreadCreate(&mThread, dconnectWorkerRun, this, 0 /*cbStack*/,
    2932                            RTTHREADTYPE_IO, RTTHREADFLAGS_WAITABLE, "DConWrk");
    2933   if (RT_FAILURE(vrc))
    2934     return NS_ERROR_FAILURE;
    2935 
    2936   return NS_OK;
    2937 }
    2938 
    2939 NS_IMETHODIMP
    2940 DConnectWorker::Run()
    2941 {
    2942   Log(("DConnect Worker thread started.\n"));
    2943 
    2944   mIsRunnable = PR_TRUE;
    2945 
    2946   nsAutoMonitor mon(mDConnect->mPendingMon);
    2947 
    2948   while (!mDConnect->mDisconnected)
    2949   {
    2950     DConnectRequest *request = mDConnect->mPendingQ.First();
    2951     if (!request)
    2952     {
    2953       mDConnect->mWaitingWorkers++;
    2954       {
    2955         // Note: we attempt to enter mWaitingWorkersMon from under mPendingMon
    2956         // here, but it should be safe because it's the only place where it
    2957         // happens. We could exit mPendingMon first, but we need to wait on it
    2958         // shorltly afterwards, which in turn will require us to enter it again
    2959         // just to exit immediately and start waiting. This seems to me a bit
    2960         // stupid (exit->enter->exit->wait).
    2961         nsAutoMonitor workersMon(mDConnect->mWaitingWorkersMon);
    2962         workersMon.NotifyAll();
    2963       }
    2964 
    2965       nsresult rv = mon.Wait();
    2966       mDConnect->mWaitingWorkers--;
    2967 
    2968       if (NS_FAILED(rv))
    2969         break;
    2970     }
    2971     else
    2972     {
    2973       Log(("DConnect Worker thread got request.\n"));
    2974 
    2975       // remove the request from the queue
    2976       mDConnect->mPendingQ.RemoveFirst();
    2977 
    2978       PRBool pendingQEmpty = mDConnect->mPendingQ.IsEmpty();
    2979       mon.Exit();
    2980 
    2981       if (pendingQEmpty)
    2982       {
    2983         nsAutoMonitor workersMon(mDConnect->mWaitingWorkersMon);
    2984         workersMon.NotifyAll();
    2985       }
    2986 
    2987       // request is processed outside the queue monitor
    2988       mDConnect->OnIncomingRequest(request->peer, request->op, request->opLen);
    2989       delete request;
    2990 
    2991       mon.Enter();
    2992     }
    2993   }
    2994 
    2995   mIsRunnable = PR_FALSE;
    2996 
    2997   Log(("DConnect Worker thread stopped.\n"));
    2998   return NS_OK;
    2999 }
    3000 
    3001 // called only on DConnect message thread
    3002 nsresult
    3003 ipcDConnectService::CreateWorker()
    3004 {
    3005   DConnectWorker *worker = new DConnectWorker(this);
    3006   if (!worker)
    3007     return NS_ERROR_OUT_OF_MEMORY;
    3008   nsresult rv = worker->Init();
    3009   if (NS_SUCCEEDED(rv))
    3010   {
    3011     nsAutoLock lock(mLock);
    3012     /* tracking an illegal join in Shutdown. */
    3013     NS_ASSERTION(!mDisconnected, "CreateWorker racing Shutdown");
    3014     if (!mWorkers.AppendElement(worker))
    3015       rv = NS_ERROR_OUT_OF_MEMORY;
    3016   }
    3017   if (NS_FAILED(rv))
    3018     delete worker;
    3019   return rv;
    3020 }
    3021 
    3022 #endif // defined(DCONNECT_MULTITHREADED) && !defined(DCONNECT_WITH_IPRT_REQ_POOL)
    3023 
    3024 //-----------------------------------------------------------------------------
    3025 
    30262875ipcDConnectService::ipcDConnectService()
    30272876 : mLock(NIL_RTSEMFASTMUTEX)
     
    30292878 , mDisconnected(PR_TRUE)
    30302879 , mStubQILock(NIL_RTSEMFASTMUTEX)
    3031 #if defined(DCONNECT_WITH_IPRT_REQ_POOL)
    30322880 , mhReqPool(NIL_RTREQPOOL)
    3033 #endif
    30342881{
    30352882}
     
    30682915    RTSemFastMutexDestroy(mLock);
    30692916
    3070 #if defined(DCONNECT_WITH_IPRT_REQ_POOL)
    30712917  RTReqPoolRelease(mhReqPool);
    30722918  mhReqPool = NIL_RTREQPOOL;
    3073 #endif
    30742919}
    30752920
     
    31152960    return NS_ERROR_OUT_OF_MEMORY;
    31162961
    3117 #if defined(DCONNECT_MULTITHREADED)
    3118 # if defined(DCONNECT_WITH_IPRT_REQ_POOL)
    31192962  vrc = RTReqPoolCreate(1024 /*cMaxThreads*/, 10*RT_MS_1SEC /*cMsMinIdle*/,
    31202963                        8 /*cThreadsPushBackThreshold */, RT_MS_1SEC /* cMsMaxPushBack */,
     
    31272970
    31282971  mDisconnected = PR_FALSE;
    3129 
    3130 # else
    3131 
    3132   mPendingMon = nsAutoMonitor::NewMonitor("DConnect pendingQ monitor");
    3133   if (!mPendingMon)
    3134     return NS_ERROR_OUT_OF_MEMORY;
    3135 
    3136   mWaitingWorkers = 0;
    3137 
    3138   mWaitingWorkersMon = nsAutoMonitor::NewMonitor("DConnect waiting workers monitor");
    3139   if (!mWaitingWorkersMon)
    3140     return NS_ERROR_OUT_OF_MEMORY;
    3141 
    3142   /* The DConnectWorker::Run method checks the ipcDConnectService::mDisconnected.
    3143    * So mDisconnect must be set here to avoid an immediate exit of the worker thread.
    3144    */
    3145   mDisconnected = PR_FALSE;
    3146 
    3147   // create a single worker thread
    3148   rv = CreateWorker();
    3149   if (NS_FAILED(rv))
    3150   {
    3151     mDisconnected = PR_TRUE;
    3152     return rv;
    3153   }
    3154 
    3155 # endif
    3156 #else
    3157 
    3158   mDisconnected = PR_FALSE;
    3159 
    3160 #endif
    3161 
    31622972  mInstance = this;
    31632973
     
    31762986  }
    31772987
    3178 #if defined(DCONNECT_MULTITHREADED)
    3179 # if defined(DCONNECT_WITH_IPRT_REQ_POOL)
    3180 
    3181 #  if defined(DCONNECT_STATS)
     2988#if defined(DCONNECT_STATS)
    31822989  fprintf(stderr, "ipcDConnectService Stats\n");
    31832990  fprintf(stderr,
     
    31922999          RTReqPoolGetStat(mhReqPool, RTREQPOOLSTAT_NS_AVERAGE_REQ_QUEUED)
    31933000          );
    3194 #  endif
     3001#endif
    31953002
    31963003  RTReqPoolRelease(mhReqPool);
    31973004  mhReqPool = NIL_RTREQPOOL;
    3198 
    3199 # else
    3200 
    3201   {
    3202     // remove all pending messages and wake up all workers.
    3203     // mDisconnected is true here and they will terminate execution after
    3204     // processing the last request.
    3205     nsAutoMonitor mon(mPendingMon);
    3206     mPendingQ.DeleteAll();
    3207     mon.NotifyAll();
    3208   }
    3209 
    3210 #if defined(DCONNECT_STATS)
    3211   fprintf(stderr, "ipcDConnectService Stats\n");
    3212   fprintf(stderr, " => number of worker threads: %d\n", mWorkers.Count());
    3213   Log(("ipcDConnectService Stats\n"));
    3214   Log((" => number of worker threads: %d\n", mWorkers.Count()));
    3215 #endif
    3216 
    3217 
    3218   // Iterate over currently running worker threads
    3219   // during VBOX_XPCOM_SHUTDOWN_TIMEOUT_MS, join() those who
    3220   // exited a working loop and abandon ones which have not
    3221   // managed to do that when timeout occurred.
    3222   Log(("Worker threads: %d\n", mWorkers.Count()));
    3223   uint64_t tsStart = RTTimeMilliTS();
    3224   while ((tsStart + VBOX_XPCOM_SHUTDOWN_TIMEOUT_MS ) > RTTimeMilliTS() && mWorkers.Count() > 0)
    3225   {
    3226     // Some array elements might be deleted while iterating. Going from the last
    3227     // to the first array element (intentionally) in order to do not conflict with
    3228     // array indexing once element is deleted.
    3229     for (int i = mWorkers.Count() - 1; i >= 0; i--)
    3230     {
    3231       DConnectWorker *worker = NS_STATIC_CAST(DConnectWorker *, mWorkers[i]);
    3232       if (worker->IsRunning() == PR_FALSE)
    3233       {
    3234         Log(("Worker %p joined.\n", worker));
    3235         worker->Join();
    3236         delete worker;
    3237         mWorkers.RemoveElementAt(i);
    3238       }
    3239     }
    3240 
    3241     /* Double-ckeck if we already allowed to quit. */
    3242     if ((tsStart + VBOX_XPCOM_SHUTDOWN_TIMEOUT_MS ) < RTTimeMilliTS() || mWorkers.Count() == 0)
    3243         break;
    3244 
    3245     // Relax a bit before the next round.
    3246     RTThreadSleep(10);
    3247   }
    3248 
    3249   Log(("There are %d thread(s) left.\n", mWorkers.Count()));
    3250 
    3251   // If there are some running threads left, terminate the process.
    3252   if (mWorkers.Count() > 0)
    3253     exit(1);
    3254 
    3255 
    3256   nsAutoMonitor::DestroyMonitor(mWaitingWorkersMon);
    3257   nsAutoMonitor::DestroyMonitor(mPendingMon);
    3258 
    3259 # endif
    3260 #endif
    32613005
    32623006  // make sure we have released all instances
     
    35293273        aSenderID, op->opcode_major, op->request_index));
    35303274
    3531 #if defined(DCONNECT_MULTITHREADED)
    3532 # if defined(DCONNECT_WITH_IPRT_REQ_POOL)
    3533 
    35343275  void *pvDataDup = RTMemDup(aData, aDataLen);
    35353276  if (RT_UNLIKELY(!pvDataDup))
     
    35403281    return NS_ERROR_FAILURE;
    35413282
    3542 # else
    3543 
    3544   nsAutoMonitor mon(mPendingMon);
    3545   mPendingQ.Append(new DConnectRequest(aSenderID, op, aDataLen));
    3546   // notify a worker
    3547   mon.Notify();
    3548   mon.Exit();
    3549 
    3550   // Yield the cpu so a worker can get a chance to start working without too much fuss.
    3551   RTThreadYield();
    3552   mon.Enter();
    3553   // examine the queue
    3554   if (mPendingQ.Count() > mWaitingWorkers)
    3555   {
    3556     // wait a little while to let the workers empty the queue.
    3557     mon.Exit();
    3558     {
    3559       nsAutoMonitor workersMon(mWaitingWorkersMon);
    3560       workersMon.Wait(PR_MIN(mWorkers.Count() / 20 + 1, 10));
    3561     }
    3562     mon.Enter();
    3563     // examine the queue again
    3564     if (mPendingQ.Count() > mWaitingWorkers)
    3565     {
    3566       // we need one more worker
    3567       nsresult rv = CreateWorker();
    3568       NS_ASSERTION(NS_SUCCEEDED(rv), "failed to create one more worker thread");
    3569       rv = rv;
    3570     }
    3571   }
    3572 
    3573 # endif
    3574 #else
    3575 
    3576   OnIncomingRequest(aSenderID, op, aDataLen);
    3577 
    3578 #endif
    3579 
    35803283  return NS_OK;
    35813284}
     
    36753378//-----------------------------------------------------------------------------
    36763379
    3677 #if defined(DCONNECT_WITH_IPRT_REQ_POOL)
    36783380/**
    36793381 * Function called by the request thread pool to process a incoming request in
     
    36873389  RTMemFree(aData);
    36883390}
    3689 #endif
    36903391
    36913392void
  • trunk/src/libs/xpcom18a4/ipc/ipcd/extensions/dconnect/src/ipcDConnectService.h

    r103476 r103488  
    3636 *
    3737 * ***** END LICENSE BLOCK ***** */
    38 
    39 // DConnect service is multithreaded by default...
    40 #if !defined(DCONNECT_SINGLETHREADED) && !defined(DCONNECT_MULTITHREADED)
    41 #define DCONNECT_MULTITHREADED
    42 # ifdef VBOX
    43 #  define DCONNECT_WITH_IPRT_REQ_POOL
    44 # endif
    45 #endif
    46 
    4738#include "ipcIDConnectService.h"
    4839#include "ipcdclient.h"
     
    6152#include "xptinfo.h"
    6253
    63 #if defined(DCONNECT_MULTITHREADED)
    64 # if defined(DCONNECT_WITH_IPRT_REQ_POOL)
    65 
    66 #  include <iprt/req.h>
    67 
    68 # else /* !DCONNECT_WITH_IPRT_REQ_POOL*/
    69 
    70 #include "ipcList.h"
    71 
    72 struct DConnectOp;
    73 
    74 struct DConnectRequest : public ipcListNode<DConnectRequest>
    75 {
    76   DConnectRequest (PRUint32 aPeer, const DConnectOp *aOp, PRUint32 aOpLen)
    77     : peer(aPeer)
    78     , opLen(aOpLen)
    79   {
    80     op = (const DConnectOp *) malloc(aOpLen);
    81     memcpy ((void *) op, aOp, aOpLen);
    82   }
    83   ~DConnectRequest() { free((void *) op); }
    84 
    85   const PRUint32 peer;
    86   const DConnectOp *op;
    87   const PRUint32 opLen;
    88 };
    89 
    90 # endif // !DCONNECT_WITH_IPRT_REQ_POOL
    91 #endif // DCONNECT_MULTITHREADED
     54#include <iprt/req.h>
    9255
    9356class nsIException;
     
    283246  NS_HIDDEN_(void) OnInvoke(PRUint32 peer, const struct DConnectInvoke *, PRUint32 opLen);
    284247
    285 #if defined(DCONNECT_MULTITHREADED)
    286 # if defined(DCONNECT_WITH_IPRT_REQ_POOL)
    287248  static DECLCALLBACK(void) ProcessMessageOnWorkerThread(ipcDConnectService *aThis, PRUint32 aSenderID, void *aData, PRUint32 aDataLen);
    288 # else
    289   NS_HIDDEN_(nsresult) CreateWorker();
    290 # endif
    291 #endif
    292249
    293250private:
     
    314271  PRBool mDisconnected;
    315272
    316 // member is never initialized or used, no point in wasting memory or making
    317 // someone believe it contains anything relevant
    318 #ifndef VBOX
    319   // our IPC client ID
    320   PRUint32 mSelfID;
    321 #endif
    322 
    323273  // global lock to protect access to protect DConnectStub::QueryInterface()
    324274  // (we cannot use mStubLock because it isn't supposed to be held long,
    325275  // like in case of an IPC call and such)
    326276  RTSEMFASTMUTEX mStubQILock;
    327 
    328 #if defined(DCONNECT_MULTITHREADED)
    329 # if defined(DCONNECT_WITH_IPRT_REQ_POOL)
    330 
    331277  /** Request pool. */
    332278  RTREQPOOL mhReqPool;
    333 
    334 # else
    335 
    336   friend class DConnectWorker;
    337 
    338   // pool of worker threads to serve incoming requests
    339   nsVoidArray mWorkers;
    340   // queue of pending requests
    341   ipcList<DConnectRequest> mPendingQ;
    342   // monitor to protect mPendingQ
    343   PRMonitor *mPendingMon;
    344   // number of waiting workers
    345   PRUint32 mWaitingWorkers;
    346   // monitor used to wait on changes in mWaitingWorkers.
    347   PRMonitor *mWaitingWorkersMon;
    348 # endif
    349 #endif
    350279
    351280  // global ipcDConnectService instance for internal usage
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette