Example #1
0
void schedule() {

    /* azioni da compiere quando non c'e' nessun thread pronto ad eseguire */
    if (emptyThreadQ(&readyQueue) && currentThread == NULL) {
        prova();
        
        if (threadCount == 1)/* se c'e' solo il SSI -> normal system shutdown */
            HALT(); /* chiamo la HALT ROM routine */
        else if (threadCount > 0 && softBlockCount == 0) {/* deadlock */
            PANIC(); /* chiamo la PANIC ROM routine */
        } else if (threadCount > 0 && softBlockCount > 0) { /* in attesa di un interrupt -> wait state */
            /* se ci sono thread in attesa dello pseudo tick,
             * carico il valore dello pseudo clock nel registro della cpu.*/
            if (!emptyThreadQ(&waitForPseudoClockQueue)) {
                SET_IT(SCHED_PSEUDO_CLOCK);
            }
            /* impostiamo lo stato del processore con gli interrupt abilitati*/
            setSTATUS(getSTATUS() | STATUS_IEc | STATUS_INT_UNMASKED);
            for (;;);
        }
    } else {
        /* Se non c'è nessun Thread in esecuzione ma c'e n'è almeno uno nella readyQueue allora 
           carico un thread*/
        if (currentThread == NULL) {
            currentThread = removeThread(&readyQueue);
            currentThread->elapsedTime = 0;
            currentThread->startTime = GET_TODLOW;
            SET_IT(SCHED_TIME_SLICE);
            /* Altrimenti se è passato il SCHED_TIME_SLICE rimuovo il thread corrente dall'esecuzione*/
        } else if (currentThread->elapsedTime >= SCHED_TIME_SLICE) {
            //in questo modo do priorità all'SSI
            if (currentThread != tcb_SSI) {
                insertThread(&readyQueue, currentThread);
                /*Carico un nuovo thread*/
                currentThread = removeThread(&readyQueue);
            }

            currentThread->elapsedTime = 0;
            currentThread->startTime = GET_TODLOW;

            /* Se e' scattato lo pseudo clock non settiamo il timer a 5 ms 
             * dato che scattera' subito l'interrupt dello pseudo clock */
            if (!isPseudoClock)
                SET_IT(SCHED_TIME_SLICE);

        }
        /* carico lo stato del thread nel processore  dalla sua tcb */
        LDST(&(currentThread->t_state));
    }
}
Example #2
0
/*
 * This function is called when the calling user-level thread ends its
 * execution. It should schedule the first user-level thread in the ready
 * queue for running.
 */
void uthread_exit() {
  sem_wait(&mutex);
    if(initialized == 0) {
      fprintf(stderr, "Error, system needs to be initialized \n");
      sem_post(&mutex);
      exit(EXIT_FAILURE);
    }

    num_running_threads--;
    struct thread* temp = removeThread();
  sem_post(&mutex);

  if(temp == NULL) {
    exit(EXIT_SUCCESS);
  }

  sem_wait(&mutex);
    if(CALLING_THREAD->type == 1) {
      num_io_threads--;
      num_running_threads++;
    }
    CALLING_THREAD = temp;
  sem_post(&mutex);

  setcontext(temp->context);
//  clone(doSetContext, (void *)malloc(16384), CLONE_VM, temp->context);
  free(temp);
}
Example #3
0
	/// Remove killed threads
	int pthread_kill(pthread_t thread, int signum) {
		if(signum == SIGKILL) {
			removeThread(thread);
		}
		
		return InterposeRoot::pthread_kill(thread, signum);
	}
Example #4
0
void* threadStarter(void *threadv) {
    Thread *thread = threadv;
    Object *callable = stackGetThisObject(thread);
    stackPop(thread);
    executeCallableExtern(callable, NULL, thread);
    removeThread(thread);
    return NULL;
}
Example #5
0
ErrorCode ProcessBase::suspend() {
  std::set<Thread *> threads;
  enumerateThreads([&](Thread *thread) { threads.insert(thread); });

  for (auto thread : threads) {
    switch (thread->state()) {
    case Thread::kInvalid:
      DS2BUG("trying to suspend tid %" PRI_PID " in state %s", thread->tid(),
             Stringify::ThreadState(thread->state()));
      break;

    case Thread::kStepped:
    case Thread::kStopped:
    case Thread::kTerminated:
      DS2LOG(Debug, "not suspending tid %" PRI_PID ", already in state %s",
             thread->tid(), Stringify::ThreadState(thread->state()));
      if (thread->state() == Thread::kTerminated) {
        removeThread(thread->tid());
      }
      break;

    case Thread::kRunning: {
      DS2LOG(Debug, "suspending tid %" PRI_PID, thread->tid());
      ErrorCode error = thread->suspend();
      switch (error) {
      case kSuccess:
        break;

      case kErrorProcessNotFound:
        DS2LOG(Debug,
               "tried to suspended tid %" PRI_PID " which is already dead",
               thread->tid());
        removeThread(thread->tid());
        return error;

      default:
        DS2LOG(Warning, "failed suspending tid %" PRI_PID ", error=%s",
               thread->tid(), Stringify::Error(error));
        return error;
      }
    } break;
    }
  }

  return kSuccess;
}
Example #6
0
ErrorCode Process::suspend() {
  std::set<Thread *> threads;
  enumerateThreads([&](Thread *thread) { threads.insert(thread); });

  for (auto thread : threads) {
    Architecture::CPUState state;
    if (thread->state() != Thread::kRunning) {
      thread->readCPUState(state);
    }
    DS2LOG(Debug, "tid %d state %d at pc %#" PRIx64, thread->tid(),
           thread->state(),
           thread->state() == Thread::kStopped ? (uint64_t)state.pc() : 0);
    if (thread->state() == Thread::kRunning) {
      ErrorCode error;

      DS2LOG(Debug, "suspending tid %d", thread->tid());
      error = thread->suspend();

      if (error == kSuccess) {
        DS2LOG(Debug, "suspended tid %d at pc %#" PRIx64, thread->tid(),
               (uint64_t)state.pc());
        thread->readCPUState(state);
      } else if (error == kErrorProcessNotFound) {
        //
        // Thread is dead.
        //
        removeThread(thread->tid());
        DS2LOG(Debug, "tried to suspended tid %d which is already dead",
               thread->tid());
      } else {
        return error;
      }
    } else if (thread->state() == Thread::kTerminated) {
      //
      // Thread is dead.
      //
      removeThread(thread->tid());
    }
  }

  return kSuccess;
}
Example #7
0
// This is a utility function for detach.
void ProcessBase::cleanup() {
  std::set<Thread *> threads;
  for (auto thread : _threads) {
    threads.insert(thread.second);
  }
  for (auto thread : threads) {
    removeThread(thread->tid());
  }
  _threads.clear();
  _currentThread = nullptr;
}
Example #8
0
 void ScriptInterface::addThread(ScriptInterface *pChild)
 {
     if (caller == pChild) return;
     if (caller)
         caller->addThread(pChild);
     else
     {
         if (pChild == this) return;
         removeThread(pChild);
         childs.push_back(pChild);
     }
 }
void vHavokCpuJobThreadPool::setNumThreads(int numThreads)
{
    if ( numThreads > MAX_NUM_THREADS )
    {
        numThreads = MAX_NUM_THREADS;
    }
    while( m_sharedThreadData.m_numThreads < numThreads )
    {
        addThread();
    }

    while( m_sharedThreadData.m_numThreads > numThreads )
    {
        removeThread();
    }
}
Example #10
0
void *create_bomb(void *arg) {
    Block *bomb;
    bomb = (Block *) arg;
    pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
    pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL);
    pthread_mutex_lock(&mutex);
    addThread(pthread_self());
    pthread_mutex_unlock(&mutex);
    while(bomb->row <= bomb->screen_height) {
        if(bomb->row == bomb->screen_height - 1) {
            pthread_mutex_lock(&mutex);
            if(bomb->col >= bomb->block->start && bomb->col <= bomb->block->end) {
                increaseScore();
                displayScore();
            } else {
                flash();
                decreaseScore(score);
                displayScore();
            }
            delete_bomb(bomb);
            pthread_mutex_unlock(&mutex);
            break;
        }
        pthread_mutex_lock(&mutex);
        SET_COLOR_BLUE;
        move(bomb->row, bomb->col);
        delch();
        insch(' ');
        (bomb->row)++;
        SET_COLOR_RED;
        pthread_mutex_unlock(&mutex);
        refresh();
        pthread_testcancel();
        napms(150);
    }

    pthread_mutex_lock(&mutex);
    bomb->cols[bomb->col] = 0;
    removeThread(pthread_self());
    pthread_mutex_unlock(&mutex);

    free(bomb);
    pthread_exit((void *) 0);
}
Example #11
0
/*
 * The calling thread requests to yield the kernel thread to another process. It
 * should save the context of current running thread and load the first one on
 * the ready queue (assuming the scheduling algorithm used is FCFS). The
 * function returns 0 on success and -1 otherwise.
 */
int uthread_yield() {
  sem_wait(&mutex);
    if(initialized == 0) {
      fprintf(stderr, "Error, system needs to be initialized \n");
      sem_post(&mutex);
      return -1;
    }
    struct thread* nextWaiting = removeThread();
    struct thread* currRun = CALLING_THREAD;

  sem_post(&mutex);

  if(nextWaiting != NULL) {
    swapcontext(currRun->context, nextWaiting->context);
    sem_wait(&mutex);
      CALLING_THREAD = nextWaiting;
    sem_post(&mutex);
    free(nextWaiting);
  }
  return 0;
}
Example #12
0
/*
 * The calling thread calls this function before it requests for I/O operations
 * (scanf, printf, read, write, etc.) We assume that when this function is
 * called, the state of the calling thread transits from running state to
 * waiting state and will not run on CPU actively. Therefore, it will create
 * a new kernel thread and schedule the first thread in the ready queue to run
 * (assuming the scheduling algorithm used is FCFS). This calling user-level
 * thread will remain associated with its current kernel thread, initiating I/O
 * and then waiting for it to complete. This function returns 0 on success and
 * -1 otherwise
 */
int uthread_startIO() {
  sem_wait(&mutex);
    if(initialized == 0) {
      fprintf(stderr, "Error, system needs to be initialized \n");
      sem_post(&mutex);
      return -1;
    }
    struct thread* temp = removeThread();
    temp->type = 1;
  sem_post(&mutex);

  if(temp != NULL) {
    sem_wait(&mutex);
      num_io_threads++;
    sem_post(&mutex);

    clone(doSetContext, malloc(16384), CLONE_VM, temp->context);
    free(temp);
  }
  return 0;
}
Example #13
0
void Thread_exit(int code) {
	BOOL result;
	T current = Thread_self();

	removeThread(current);
	ENTERCRITICAL;
	if (current->joinlist != NULL) {
		T t, n;
		int count = 0;
		assert(current->join);
		for (t = current->joinlist; t != NULL; t = n) {
			t->code = code;
			n = t->link;
			t->link = NULL;
			count++;
		}
		current->joinlist = NULL;
		result = ReleaseSemaphore(current->join, count, NULL);
		assert(result == TRUE);
	}
	result = CloseHandle(current->join);
	assert(result == TRUE);
	current->join = NULL;
	if (join0count > 0 && nthreads == 1) {
		assert(join0count == 1);
		result = ReleaseSemaphore(join0, 1, NULL);
		assert(result == TRUE);
	}
	if (nthreads == 0) {
		result = CloseHandle(join0);
		assert(result == TRUE);
	}
	FREE(current);
	LEAVECRITICAL;
	_endthreadex(code);
}
Example #14
0
void ProcessBase::remove(ThreadBase *thread) { removeThread(thread->tid()); }
Example #15
0
ErrorCode Process::wait(int *rstatus) {
  int status, signal;
  ProcessInfo info;
  ErrorCode err;
  pid_t tid;

  // We have at least one thread when we start waiting on a process.
  DS2ASSERT(!_threads.empty());

continue_waiting:
  err = super::wait(&status);
  if (err != kSuccess)
    return err;

  DS2LOG(Debug, "stopped: status=%d", status);

  if (WIFEXITED(status)) {
    err = super::wait(&status);
    DS2LOG(Debug, "exited: status=%d", status);
    _currentThread->updateStopInfo(status);
    _terminated = true;
    if (rstatus != nullptr) {
      *rstatus = status;
    }

    return kSuccess;
  }

  DS2BUG("not implemented");
  switch (_currentThread->_stopInfo.event) {
  case StopInfo::kEventNone:
    switch (_currentThread->_stopInfo.reason) {
    case StopInfo::kReasonNone:
      ptrace().resume(ProcessThreadId(_pid, tid), info);
      goto continue_waiting;
    default:
      DS2ASSERT(false);
      goto continue_waiting;
    }

  case StopInfo::kEventExit:
  case StopInfo::kEventKill:
    DS2LOG(Debug, "thread %d is exiting", tid);

    //
    // Killing the main thread?
    //
    // Note(sas): This might be buggy; the main thread exiting
    // doesn't mean that the process is dying.
    //
    if (tid == _pid && _threads.size() == 1) {
      DS2LOG(Debug, "last thread is exiting");
      break;
    }

    //
    // Remove and release the thread associated with this pid.
    //
    removeThread(tid);
    goto continue_waiting;

  case StopInfo::kEventStop:
    if (getInfo(info) != kSuccess) {
      DS2LOG(Error, "couldn't get process info for pid %d", _pid);
      goto continue_waiting;
    }

    signal = _currentThread->_stopInfo.signal;

    if (signal == SIGSTOP || signal == SIGCHLD) {
      //
      // Silently ignore SIGSTOP, SIGCHLD and SIGRTMIN (this
      // last one used for thread cancellation) and continue.
      //
      // Note(oba): The SIGRTMIN defines expands to a glibc
      // call, this due to the fact the POSIX standard does
      // not mandate that SIGRT* defines to be user-land
      // constants.
      //
      // Note(sas): This is probably partially dead code as
      // ptrace().step() doesn't work on ARM.
      //
      // Note(sas): Single-step detection should be higher up, not
      // only for SIGSTOP, SIGCHLD and SIGRTMIN, but for every
      // signal that we choose to ignore.
      //
      bool stepping = (_currentThread->state() == Thread::kStepped);

      if (signal == SIGSTOP) {
        signal = 0;
      } else {
        DS2LOG(Debug, "%s due to special signal, tid=%d status=%#x signal=%s",
               stepping ? "stepping" : "resuming", tid, status,
               strsignal(signal));
      }

      ErrorCode error;
      if (stepping) {
        error = ptrace().step(ProcessThreadId(_pid, tid), info, signal);
      } else {
        error = ptrace().resume(ProcessThreadId(_pid, tid), info, signal);
      }

      if (error != kSuccess) {
        DS2LOG(Warning, "cannot resume thread %d error=%d", tid, error);
      }

      goto continue_waiting;
    } else if (_passthruSignals.find(signal) != _passthruSignals.end()) {
      ptrace().resume(ProcessThreadId(_pid, tid), info, signal);
      goto continue_waiting;
    } else {
      //
      // This is a signal that we want to transmit back to the
      // debugger.
      //
      break;
    }
  }

  if (!(WIFEXITED(status) || WIFSIGNALED(status))) {
    //
    // Suspend the process, this must be done after updating
    // the thread trap info.
    //
    suspend();
  }

  if ((WIFEXITED(status) || WIFSIGNALED(status))) {
    _terminated = true;
  }

  if (rstatus != nullptr) {
    *rstatus = status;
  }

  return kSuccess;
}
Example #16
0
File: Process.cpp Project: sas/ds2
ErrorCode Process::wait() {
  int status, signal;
  bool stepping;
  ProcessInfo info;
  ThreadId tid;

  // We have at least one thread when we start waiting on a process.
  DS2ASSERT(!_threads.empty());

  while (!_threads.empty()) {
    tid = blocking_waitpid(-1, &status, __WALL);
    if (tid <= 0) {
      return kErrorProcessNotFound;
    }

    DS2LOG(Debug, "tid %" PRI_PID " %s", tid, Stringify::WaitStatus(status));

    auto threadIt = _threads.find(tid);

    if (threadIt == _threads.end()) {
      // If we don't know about this thread yet, but it has a WIFEXITED() or a
      // WIFSIGNALED() status (i.e.: it terminated), it means we already
      // cleaned up the thread object (e.g.: in Process::suspend), but we
      // hadn't waitpid()'d it yet. Avoid re-creating a Thread object here.
      if (WIFEXITED(status) || WIFSIGNALED(status)) {
        goto continue_waiting;
      }

      // A new thread has appeared that we didn't know about. Create the
      // Thread object and return.
      DS2LOG(Debug, "creating new thread tid=%d", tid);
      _currentThread = new Thread(this, tid);
      return kSuccess;
    } else {
      _currentThread = threadIt->second;
    }

    stepping = _currentThread->_state == Thread::kStepped;
    _currentThread->updateStopInfo(status);

    switch (_currentThread->_stopInfo.event) {
    case StopInfo::kEventNone:
      // If the thread is stopped for no reason, it means the debugger (ds2)
      // sent a SIGSTOP to it while it was already stopped for another reason,
      // the SIGSTOP was queued, and now we're getting this notification. We
      // have to ignore this and just let the thread continue.
      // If `stepping` is true, it means the thread was actually being
      // single-stepped before stopping, so instead of doing a `resume()`, we
      // have to do a new `step()`.
      if (stepping) {
        _currentThread->step();
      } else {
        _currentThread->resume();
      }
      goto continue_waiting;

    case StopInfo::kEventExit:
    case StopInfo::kEventKill:
      DS2LOG(Debug, "thread %d is exiting", tid);

      //
      // Killing the main thread?
      //
      // Note(sas): This might be buggy; the main thread exiting
      // doesn't mean that the process is dying.
      //
      if (tid == _pid && _threads.size() == 1) {
        DS2LOG(Debug, "last thread is exiting");
        break;
      }

      //
      // Remove and release the thread associated with this pid.
      //
      removeThread(tid);
      goto continue_waiting;

    case StopInfo::kEventStop:
      signal = _currentThread->_stopInfo.signal;

      DS2LOG(Debug, "stopped tid=%" PRI_PID " status=%#x signal=%s", tid,
             status, Stringify::Signal(signal));

      if (_passthruSignals.find(signal) != _passthruSignals.end()) {
        DS2LOG(Debug, "%s passed through to thread %" PRI_PID ", not stopping",
               Stringify::Signal(signal), tid);
        _currentThread->resume(signal);
        goto continue_waiting;
      } else {
        //
        // This is a signal that we want to transmit back to the
        // debugger.
        //
        break;
      }
    }

    break;

  continue_waiting:
    _currentThread = nullptr;
    continue;
  }

  if (!(WIFEXITED(status) || WIFSIGNALED(status)) || tid != _pid) {
    //
    // Suspend the process, this must be done after updating
    // the thread trap info.
    //
    suspend();
  }

  if ((WIFEXITED(status) || WIFSIGNALED(status)) && tid == _pid) {
    _terminated = true;
  }

  return kSuccess;
}
Example #17
0
ErrorCode Process::wait() {
  int status, signal;
  ProcessInfo info;
  ThreadId tid;

  // We have at least one thread when we start waiting on a process.
  DS2ASSERT(!_threads.empty());

  while (!_threads.empty()) {
    tid = blocking_waitpid(-1, &status, __WALL);
    DS2LOG(Debug, "wait tid=%d status=%#x", tid, status);

    if (tid <= 0)
      return kErrorProcessNotFound;

    auto threadIt = _threads.find(tid);

    if (threadIt == _threads.end()) {
      // If we don't know about this thread yet, but it has a WIFEXITED() or a
      // WIFSIGNALED() status (i.e.: it terminated), it means we already
      // cleaned up the thread object (e.g.: in Process::suspend), but we
      // hadn't waitpid()'d it yet. Avoid re-creating a Thread object here.
      if (WIFEXITED(status) || WIFSIGNALED(status)) {
        goto continue_waiting;
      }

      // A new thread has appeared that we didn't know about. Create the
      // Thread object and return.
      DS2LOG(Debug, "creating new thread tid=%d", tid);
      _currentThread = new Thread(this, tid);
      return kSuccess;
    } else {
      _currentThread = threadIt->second;
    }

    _currentThread->updateStopInfo(status);

    switch (_currentThread->_stopInfo.event) {
    case StopInfo::kEventNone:
      _currentThread->resume();
      goto continue_waiting;

    case StopInfo::kEventExit:
    case StopInfo::kEventKill:
      DS2LOG(Debug, "thread %d is exiting", tid);

      //
      // Killing the main thread?
      //
      // Note(sas): This might be buggy; the main thread exiting
      // doesn't mean that the process is dying.
      //
      if (tid == _pid && _threads.size() == 1) {
        DS2LOG(Debug, "last thread is exiting");
        break;
      }

      //
      // Remove and release the thread associated with this pid.
      //
      removeThread(tid);
      goto continue_waiting;

    case StopInfo::kEventStop:
      signal = _currentThread->_stopInfo.signal;

      DS2LOG(Debug, "stopped tid=%d status=%#x signal=%s", tid, status,
             Stringify::Signal(signal));

      if (_passthruSignals.find(signal) != _passthruSignals.end()) {
        _currentThread->resume(signal);
        goto continue_waiting;
      } else {
        //
        // This is a signal that we want to transmit back to the
        // debugger.
        //
        break;
      }
    }

    break;

  continue_waiting:
    _currentThread = nullptr;
    continue;
  }

  if (!(WIFEXITED(status) || WIFSIGNALED(status)) || tid != _pid) {
    //
    // Suspend the process, this must be done after updating
    // the thread trap info.
    //
    suspend();
  }

  if ((WIFEXITED(status) || WIFSIGNALED(status)) && tid == _pid) {
    _terminated = true;
  }

  return kSuccess;
}
Example #18
0
ErrorCode Process::wait(int *status, bool hang) {
  if (_terminated)
    return kSuccess;

  DEBUG_EVENT de;
  bool keepGoing = true;

  while (keepGoing) {
    BOOL result = WaitForDebugEvent(&de, hang ? INFINITE : 0);
    if (!result)
      return Platform::TranslateError();

    keepGoing = false;

    switch (de.dwDebugEventCode) {
    case CREATE_PROCESS_DEBUG_EVENT:
#define CHECK_AND_CLOSE(HAN)                                                   \
  do {                                                                         \
    if ((de.u.CreateProcessInfo.HAN) != NULL)                                  \
      CloseHandle(de.u.CreateProcessInfo.HAN);                                 \
  } while (0)
      CHECK_AND_CLOSE(hFile);
      CHECK_AND_CLOSE(hProcess);
      CHECK_AND_CLOSE(hThread);
#undef CHECK_AND_CLOSE
      return kSuccess;

    case EXIT_PROCESS_DEBUG_EVENT:
      _terminated = true;
      return kSuccess;

    case CREATE_THREAD_DEBUG_EVENT: {
      auto threadHandle = de.u.CreateThread.hThread;
      auto tid = GetThreadId(threadHandle);
      // No need to save the new thread pointer, as it gets added automatically
      // to the process.
      new Thread(this, tid, threadHandle);
      resume();
      keepGoing = true;
    } break;

    case EXIT_THREAD_DEBUG_EVENT: {
      auto threadIt = _threads.find(de.dwThreadId);
      DS2ASSERT(threadIt != _threads.end());
      auto tid = threadIt->second->tid();
      ContinueDebugEvent(_pid, tid, DBG_CONTINUE);
      removeThread(threadIt->second->tid());
      keepGoing = true;
    } break;

    case RIP_EVENT:
      DS2LOG(Fatal, "debug event RIP");

    case EXCEPTION_DEBUG_EVENT:
    case LOAD_DLL_DEBUG_EVENT:
    case UNLOAD_DLL_DEBUG_EVENT:
    case OUTPUT_DEBUG_STRING_EVENT: {
      auto threadIt = _threads.find(de.dwThreadId);
      DS2ASSERT(threadIt != _threads.end());
      threadIt->second->updateState(de);
    } break;

    default:
      DS2BUG("unknown debug event code: %lu", de.dwDebugEventCode);
    }
  }

  return kSuccess;
}
Example #19
0
	/// Intercept calls to pthread_exit
	void pthread_exit(void* retval) {
		removeThread(InterposeRoot::pthread_self());
		InterposeRoot::pthread_exit(retval);
	}
Example #20
0
	/// Remove cancelled threads
	int pthread_cancel(pthread_t thread) {
		removeThread(thread);
		return InterposeRoot::pthread_cancel(thread);
	}