Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8209671

With dynamic compiler threads the compiler-thread count is not maintained in a thread-safe manner

    XMLWordPrintable

Details

    • Bug
    • Status: Closed
    • P3
    • Resolution: Not an Issue
    • 11, 12
    • 12
    • hotspot
    • None
    • b11
    • 11

    Description

      This is the code that updates the compiler thread count:

      static bool can_remove(CompilerThread *ct, bool do_it) {
        assert(UseDynamicNumberOfCompilerThreads, "or shouldn't be here");
        if (!ReduceNumberOfCompilerThreads) return false;

        AbstractCompiler *compiler = ct->compiler();
        int compiler_count = compiler->num_compiler_threads();
        bool c1 = compiler->is_c1();

        // Keep at least 1 compiler thread of each type.
        if (compiler_count < 2) return false;

        // Keep thread alive for at least some time.
        if (ct->idle_time_millis() < (c1 ? 500 : 100)) return false;

        // We only allow the last compiler thread of each type to get removed.
        jobject last_compiler = c1 ? CompileBroker::compiler1_object(compiler_count - 1)
                                   : CompileBroker::compiler2_object(compiler_count - 1);
        if (oopDesc::equals(ct->threadObj(), JNIHandles::resolve_non_null(last_compiler))) {
          if (do_it) {
            assert_locked_or_safepoint(CompileThread_lock); // Update must be consistent.
            compiler->set_num_compiler_threads(compiler_count - 1);
          }
          return true;
        }
        return false;
      }

      We read the count initially with no lock held:

        int compiler_count = compiler->num_compiler_threads();

      we then later update the count with the lock held:

            assert_locked_or_safepoint(CompileThread_lock); // Update must be consistent.
            compiler->set_num_compiler_threads(compiler_count - 1);

      but by this time the local variable "compiler_count" may not contain the current number of compiler threads and so we will set the wrong value. Further the count may also have changed when we use it here:

       jobject last_compiler = c1 ? CompileBroker::compiler1_object(compiler_count - 1)
                                   : CompileBroker::compiler2_object(compiler_count - 1);

      In addition there is logic to try and ensure we always keep at least one compiler thread but this seems to be executed with no locking so multiple threads can execute:

        if (compiler_count < 2) return false;

      and all see a count >=2 but then all continue to exit thus leaving zero compiler threads running.

      Attachments

        Issue Links

          Activity

            People

              mdoerr Martin Doerr
              dholmes David Holmes
              Votes:
              0 Vote for this issue
              Watchers:
              3 Start watching this issue

              Dates

                Created:
                Updated:
                Resolved: