예제 #1
0
        static void Main(string[] args)
        {
            var db            = new SingletonDB();
            var workerPool    = new WorkerPool("Hen");
            var queue         = new FIFOQueue(workerPool, db);
            var scheduler     = new LazyScheduler(queue);
            var workerFactory = new ClousotWorkerFactory(scheduler, null, db);

            scheduler.FeedQueue(new ISliceId[0]); // TODO: call slicer

            var numberOfWorkers = Environment.ProcessorCount;

            numberOfWorkers = 1;

            for (var i = 0; i < numberOfWorkers; i++)
            {
                workerPool.CreateWorker(workerFactory);
            }

            workerPool.WaitAll();
            workerPool.StopAll();
        }
예제 #2
0
        // Entry point
        public static int Main(string[] args, ISimpleLineWriter output)
        {
            var start          = DateTime.Now;
            var slicingOptions = new SlicingOptions(args);

            // we use it to parse the clousot options, and to split the work
            var clousot = new NewCCI2Driver(slicingOptions.remainingArgs.ToArray(), output);

            if (!clousot.CheckOptions())
            {
                return(-1);
            }

            var                   errorCode                      = 0;
            WorkerPool            workerPool                     = null;
            IQueue                queue                          = null;
            IWorkerFactory        localWorkerFactory             = null;
            List <IWorkerFactory> remoteWorkerFactories          = null;
            Func <SliceDefinition, ISliceWorkResult> workOnSlice = null;
            Dictionary <ISliceId, int> failedRegressions         = null;

            var localWorkers  = slicingOptions.LocalWorkers;
            var remoteWorkers = slicingOptions.RemoteWorkers;
            var workers       = localWorkers + remoteWorkers;


            // If we have workers, we create a Worker factory
            if (workers > 0)
            {
                IDB db;
                if (remoteWorkers > 0 || clousot.options.useCache)
                {
                    // Use Clousot Database
                    db = new StdDB(clousot.options);
                }
                else
                {
                    // In-memory database
                    db = new MemorySingletonDB();
                }

                workerPool = new WorkerPool("Worker", canCancel: false);
                queue      = new FIFOQueue(workerPool, db);

                // When a job is done, it choses which jobs to put in the queue (e.g., analyze the dependencies)
                var scheduler =
                    clousot.options.InferObjectInvariantsOnlyForReadonlyFields?
                    new LazySchedulerForObjectInvariants(queue, db) : // use LazySchedulerForObjectInvariants for global fixpoint computation including object invariants
                    new LazyScheduler(queue, db);                     // use LazyScheduler for the global fixpoint computation

                //var scheduler = new NoloopScheduler(queue);

                // Usual cache
                var clousotDB = slicingOptions.useDB ? db : null;

                var argsForWorker = clousot.argsForWorker.ToFList();

                if (localWorkers > 0)
                {
                    if (slicingOptions.cci1)
                    {
                        localWorkerFactory = new Clousot1WorkerFactory(scheduler, argsForWorker, output, clousotDB);
                    }
                    else
                    {
                        localWorkerFactory = new Clousot2WorkerFactory(scheduler, argsForWorker, output, clousotDB);
                    }
                    // TODO: use a lighter version of ClousotMain since options are already checked here
                }
                if (remoteWorkers > 0) // so far 1 factory per remote worker but we can do better
                {
                    // TODO: specifiy, for each address the number of workers

                    // We have a list, because we can have several addresses
                    remoteWorkerFactories = slicingOptions.serviceAddress.Select(addr => new Clousot2SWorkerFactory(scheduler, argsForWorker, output, addr)).ToList <IWorkerFactory>();
                }

                if (clousot.options.IsRegression)
                {
                    failedRegressions = new Dictionary <ISliceId, int>();
                }

                // fail if any work fails
                scheduler.OnWorkDone += (sliceId, returnCode) =>
                {
                    if (errorCode >= 0)
                    {
                        if (returnCode < 0) // special error code, keep only one
                        {
                            errorCode = returnCode;
                        }
                        else
                        {
                            int prevValue;
                            if (clousot.options.IsRegression)
                            {
                                lock (failedRegressions)
                                {
                                    Contract.Assume(failedRegressions != null);
                                    if (failedRegressions.TryGetValue(sliceId, out prevValue))
                                    {
                                        output.WriteLine("[Regression] We already analyzed {0} with outcome {1}. Now we update the outcome to {2}", sliceId.Dll, prevValue, returnCode);
                                    }
                                    failedRegressions[sliceId] = returnCode;
                                }
                            }
                            errorCode += returnCode; // regression error count, additive
                        }
                    }
                };

                // What we do for each slice. Two things:
                // 1. Register the slice in the db
                // 2. Add to the queue (via the scheduler, who decides how to do it)
                workOnSlice = sliceDef =>
                {
                    var sliceId = db.RegisterSlice(sliceDef);
                    scheduler.FeedQueue(new ISliceId[] { sliceId });
                    return(null);
                };
            }

            ISlicerResult slicerResult = null;

            if (slicingOptions.sliceFirst)
            {
                slicerResult = clousot.SplitWork(workOnSlice);
                output.WriteLine("Slicing time: {0}", DateTime.Now - start);
            }

            if (workerPool != null)
            {
                if (localWorkerFactory != null)
                {
                    for (var i = 0; i < localWorkers; i++)
                    {
                        workerPool.CreateWorker(localWorkerFactory);
                    }
                }
                if (remoteWorkerFactories != null)
                {
                    foreach (var factory in remoteWorkerFactories)
                    {
                        workerPool.CreateWorker(factory);
                    }
                }
            }

            if (!slicingOptions.sliceFirst)
            {
                slicerResult = clousot.SplitWork(workOnSlice);
                output.WriteLine("Slicing time and thread creation time : {0}", DateTime.Now - start);
            }

            if (workerPool != null)
            {
                // workerPool != null ==> queue != null
                Contract.Assume(queue != null);
                workerPool.WaitAllAnd(queue.EmptyQueueWaitHandle);
                // Something else can arrive at the queue, so we want to stop all of them
                workerPool.StopAll();
            }

            if (slicerResult != null)
            {
                var errors = slicerResult.GetErrors();
                if (errors.Any())
                {
                    foreach (var errMessage in errors)
                    {
                        output.WriteLine(errMessage);
                    }
                    errorCode = errors.Count();
                }
            }

            output.WriteLine("Total analysis time: {0}", DateTime.Now - start);

            var returnValue = errorCode;

            if (failedRegressions != null && clousot.options.IsRegression && errorCode >= 0)
            {
                returnValue = failedRegressions.Where(pair => pair.Value != 0).Select(pair => Math.Abs(pair.Value)).Sum();
            }

#if DEBUG
            if (clousot.options.IsRegression)
            {
                Console.WriteLine("[Regression] Returned value {0}", returnValue);
            }
#endif
            return(returnValue);
        }