Пример #1
0
  void FinalizerHandler::perform(STATE) {
    GCTokenImpl gct;
    utilities::thread::Thread::set_os_name("rbx.finalizer");

    state->vm()->thread->hard_unlock(state, gct);

    while(!exit_) {
      if(!process_list_) first_process_item();

      if(!process_list_) {
        utilities::thread::Mutex::LockGuard lg(worker_lock_);

        if(finishing_) supervisor_signal();

        // exit_ might have been set in the mean while after
        // we grabbed the worker_lock
        if(!exit_) {
          GCIndependent indy(state);
          worker_wait();
        }

        continue;
      }

      finalize(state);
      next_process_item();
    }
  }
Пример #2
0
  void FinalizerHandler::finish(STATE, GCToken gct) {
    if(!self_) {
      if(process_list_ || !lists_->empty() || !live_list_->empty()) {
        rubinius::bug("FinalizerHandler worker thread dead during halt");
      } else {
        return;
      }
    }

    finishing_ = true;

    while(true) {
      {
        StopTheWorld stw(state, gct, 0);

        if(!process_list_) {
          if(live_list_->empty() && lists_->empty()) break;

          // Everything is garbage when halting so keep adding live objects to
          // finalize queue until done.
          if(!live_list_->empty()) {
            for(FinalizeObjects::iterator i = live_list_->begin();
                i != live_list_->end();
                ++i)
            {
              i->queued();
            }

            queue_objects();
          }

          first_process_item();
          if(!process_list_) break;
        }
      }

      worker_signal();

      {
        utilities::thread::Mutex::LockGuard lg(supervisor_lock_);

        state->vm()->set_call_frame(0);
        GCIndependent indy(state);
        if(process_list_) supervisor_wait();
      }
    }

    if(!lists_->empty() || !live_list_->empty() || process_list_ != NULL)
      rubinius::bug("FinalizerHandler exiting with pending finalizers");

    stop_thread(state);
  }
Пример #3
0
  void SignalHandler::perform(STATE) {
#ifndef RBX_WINDOWS
    sigset_t set;
    sigfillset(&set);
    pthread_sigmask(SIG_BLOCK, &set, NULL);
#endif

    GCTokenImpl gct;
    utilities::thread::Thread::set_os_name("rbx.signal-dispatch");

    state->vm()->thread->hard_unlock(state, gct);

    for(;;) {
      fd_set fds;
      FD_ZERO(&fds);
      FD_SET((int_fd_t)read_fd_, &fds);

      int n;

      {
        GCIndependent indy(state, 0);
        n = select(read_fd_ + 1, &fds, NULL, NULL, NULL);
      }

      if(n == 1) {
        // drain a bunch
        char buf[512];
        if(read(read_fd_, buf, sizeof(buf)) < 0) {
          perror("SignalHandler::perform failed to read");
        }

        if(exit_) {
          self_ = 0;
          return;
        }

        {
          target_->check_local_interrupts = true;
          target_->wakeup(state, gct);

        }
      }
    }
  }
Пример #4
0
  void ObjectMemory::in_finalizer_thread(STATE) {
    CallFrame* call_frame = 0;
    utilities::thread::Thread::set_os_name("rbx.finalizer");

    GCTokenImpl gct;
    state->vm()->thread->hard_unlock(state, gct);

    // Forever
    for(;;) {
      FinalizeObject* fi;

      // Take the lock, remove the first one from the list,
      // then process it.
      {
        SCOPE_LOCK(state->vm(), finalizer_lock_);

        state->vm()->set_call_frame(0);

        while(to_finalize_.empty()) {
          GCIndependent indy(state);
          finalizer_var_.wait(finalizer_lock_);
        }

        fi = to_finalize_.front();
        to_finalize_.pop_front();
      }

      if(fi->finalizer) {
        (*fi->finalizer)(state, fi->object);
        // Unhook any handle used by fi->object so that we don't accidentally
        // try and mark it later (after we've finalized it)
        if(capi::Handle* handle = fi->object->handle(state)) {
          handle->forget_object();
          fi->object->clear_handle(state);
        }

        // If the object was remembered, unremember it.
        if(fi->object->remembered_p()) {
          unremember_object(fi->object);
        }
      } else if(fi->ruby_finalizer) {
        // Rubinius specific code. If the finalizer is cTrue, then
        // send the object the finalize message
        if(fi->ruby_finalizer == cTrue) {
          fi->object->send(state, call_frame, state->symbol("__finalize__"));
        } else {
          Array* ary = Array::create(state, 1);
          ary->set(state, 0, fi->object->id(state));

          OnStack<1> os(state, ary);

          fi->ruby_finalizer->send(state, call_frame, G(sym_call), ary);
        }
      } else {
        std::cerr << "Unsupported object to be finalized: "
                  << fi->object->to_s(state)->c_str(state) << std::endl;
      }

      fi->status = FinalizeObject::eFinalized;
    }

    state->checkpoint(gct, 0);
  }