Пример #1
0
/*
  The gtthread_join() function is analogous to pthread_join.
  All gtthreads are joinable.
 */
int gtthread_join(gtthread_t thread, void **status)
{
    /* if a thread tries to join itself */
    if (thread == current->tid)
        return -1;

    thread_t* t;
    /* if a thread is not created */
    if ((t = thread_get(thread)) == NULL)
        return -1;

    /* check if that thread is joining on me */
    if (t->joining == current->tid)
        return -1;

    current->joining = t->tid;
    /* wait on the thread to terminate */
    while (t->state == GTTHREAD_RUNNING)
    {
        sigprocmask(SIG_UNBLOCK, &vtalrm, NULL);
        sigvtalrm_handler(SIGVTALRM);
        sigprocmask(SIG_BLOCK, &vtalrm, NULL);
    }

    if (status == NULL)
        return 0;

    if (t->state == GTTHREAD_CANCEL)
        *status = (void*) GTTHREAD_CANCEL;
    else if (t->state == GTTHREAD_DONE)
        *status = t->retval;

    return 0;
}
Пример #2
0
/*
  The gtthread_cancel() function is analogous to pthread_cancel,
  allowing one thread to terminate another asynchronously.
 */
int gtthread_cancel(gtthread_t thread)
{
    /* if a thread cancel itself */
    if (gtthread_equal(current->tid, thread))
        gtthread_exit(0);

    sigprocmask(SIG_BLOCK, &vtalrm, NULL);
    thread_t* t = thread_get(thread);
    if (t == NULL)
    {
        sigprocmask(SIG_UNBLOCK, &vtalrm, NULL);    
        return -1;
    }
    if (t->state == GTTHREAD_DONE)
    {
        sigprocmask(SIG_UNBLOCK, &vtalrm, NULL); 
        return -1;
    }
    if (t->state == GTTHREAD_CANCEL)
    {
        sigprocmask(SIG_UNBLOCK, &vtalrm, NULL);  
        return -1;
    }
    else
        t->state = GTTHREAD_CANCEL;

    free(t->ucp->uc_stack.ss_sp);
    free(t->ucp);
    t->ucp = NULL;
    t->joining = 0;
    steque_enqueue(&zombie_queue, t);
    sigprocmask(SIG_UNBLOCK, &vtalrm, NULL);
    return 0;
}
Пример #3
0
static int
gen_traffic(void *priv, enum VSL_tag_e tag, unsigned fd,
    unsigned len, unsigned spec, const char *ptr, uint64_t bitmap)
{
	struct replay_thread *thr;
	struct message *msg;

	(void)priv;
	(void)bitmap;

	if (fd == 0 || !(spec & VSL_S_CLIENT))
		return (0);

	thread_log(3, 0, "%d %s", fd, VSL_tags[tag]);
	thr = thread_get(fd, replay_thread);
	if (thr == NULL)
		return (0);
	msg = malloc(sizeof (struct message));
	msg->tag = tag;
	msg->len = len;
	msg->ptr = malloc(len);
	AN(msg->ptr);
	memcpy(msg->ptr, ptr, len);
	mailbox_put(&thr->mbox, msg);

	return (0);
}
Пример #4
0
static void thread_block_mutex(ThreadId tid, struct mutex *mx)
{
   struct thread *th = thread_get(tid);

   if (th == NULL) {
      /* should an unknown thread doing something make it spring to life? */
      thread_report(tid, THE_NotExist, "blocking on mutex");
      return;
   }
   switch(th->state) {
   case TS_Dead:
   case TS_Zombie:
      thread_report(th->tid, THE_NotAlive, "blocking on mutex");
      break;

   case TS_MutexBlocked:
   case TS_CVBlocked:
   case TS_JoinBlocked:
      thread_report(th->tid, THE_Blocked, "blocking on mutex");
      break;

   case TS_Alive:
   case TS_Running:		/* OK */
      break;
   }

   do_thread_block_mutex(th, mx);
}
Пример #5
0
int event_remv(int id, int event) {
	struct thread *thread = thread_get(id);

	if (!thread) {
		return 1;
	}

	if (event < 0 || event >= EV_COUNT) {
		return 1;
	}

	if (!evqueue[event].front_thread) {
		return 1;
	}

	if (evqueue[event].front_thread == thread) {
		evqueue[event].front_thread = thread->next;
		if (evqueue[event].back_thread == thread) {
			evqueue[event].back_thread = NULL;
		}
		return 0;
	}
	else for (struct thread *t = evqueue[event].front_thread; t->next; t = t->next) {
		if (t->next == thread) {
			t->next = thread->next;
			if (evqueue[event].back_thread == thread) {
				evqueue[event].back_thread = t;
			}
			return 0;
		}
	}

	return 1;
}
Пример #6
0
static void thread_unblock_mutex(ThreadId tid, struct mutex *mx, const Char *action)
{
   struct thread *th = thread_get(tid);

   if (th == NULL) {
      /* should an unknown thread doing something make it spring to life? */
      thread_report(tid, THE_NotExist, "giving up on mutex");
      return;
   }

   switch(th->state) {
   case TS_MutexBlocked:	/* OK */
      break;

   case TS_Alive:
   case TS_Running:
      thread_report(tid, THE_NotBlocked, action);
      break;

   case TS_CVBlocked:
   case TS_JoinBlocked:
      thread_report(tid, THE_Blocked, action);
      break;

   case TS_Dead:
   case TS_Zombie:
      thread_report(tid, THE_NotAlive, action);
      break;
   }

   do_thread_run(th);
}
static int
gen_traffic(void *priv, enum shmlogtag tag, unsigned fd,
    unsigned len, unsigned spec, const char *ptr)
{
	struct replay_thread *thr;
	const char *end;
	struct message *msg;

	(void)priv;

	end = ptr + len;

	if (fd == 0 || !(spec & VSL_S_CLIENT))
		return (0);

	thread_log(3, 0, "%d %s", fd, VSL_tags[tag]);
	thr = thread_get(fd, replay_thread);
	if (thr == NULL)
		return (0);
	msg = malloc(sizeof (struct message));
	msg->tag = tag;
	msg->len = len;
	msg->ptr = strndup(ptr, len);
	mailbox_put(&thr->mbox, msg);

	return (0);
}
Пример #8
0
t_error ia32_thread_store(i_thread thr, t_thread_context* ctx)
{
  o_thread* o;
  thread_get(thr, &o);
  ctx->sp = o->machdep.named.esp;
  ctx->pc = o->machdep.named.eip;
  return ERROR_NONE;
}
Пример #9
0
Файл: main.c Проект: mali/RIOT
/* Mostly copied from thread_wakeup() */
static void _thread_wake_wo_yield(kernel_pid_t pid)
{
    unsigned old_state = irq_disable();

    thread_t *other_thread = (thread_t *) thread_get(pid);

    sched_set_status(other_thread, STATUS_RUNNING);

    irq_restore(old_state);
}
Пример #10
0
t_error ia32_thread_load(i_thread thr,t_thread_context ctx)
{
  o_thread* o;
  thread_get(thr, &o);
  o->machdep.named.esp = ctx.sp;
  //printf("[%i", o->machdep.named.esp = ctx.sp);
  //printf("@%i]\n", &(o->machdep.named));
  o->machdep.named.eip = ctx.pc;
  gdt_build_selector(PMODE_GDT_CORE_CS, ia32_prvl_supervisor, &o->machdep.named.cs);
  return ERROR_NONE;
}
Пример #11
0
/* Finish unlocking a Mutex.  The mutex can validly be in one of three
   states:
   - Unlocking
   - Locked, owned by someone else (someone else got it in the meantime)
   - Free (someone else completed a lock-unlock cycle)
 */
void VG_(tm_mutex_unlock)(ThreadId tid, Addr mutexp)
{
   struct mutex *mx;
   struct thread *th;

   mx = mutex_check_initialized(tid, mutexp, "unlocking mutex");

   th = thread_get(tid);

   if (th == NULL)
      thread_report(tid, THE_NotExist, "unlocking mutex");
   else {
      switch(th->state) {
      case TS_Alive:
      case TS_Running:		/* OK */
	 break;

      case TS_Dead:
      case TS_Zombie:
	 thread_report(tid, THE_NotAlive, "unlocking mutex");
	 break;

      case TS_JoinBlocked:
      case TS_CVBlocked:
      case TS_MutexBlocked:
	 thread_report(tid, THE_Blocked, "unlocking mutex");
	 do_thread_run(th);
	 break;
      }
   }

   switch(mx->state) {
   case MX_Locked:
      /* Someone else might have taken ownership in the meantime */
      if (mx->owner == tid)
	 mutex_report(tid, mutexp, MXE_Locked, "unlocking");
      break;

   case MX_Free:
      /* OK - nothing to do */
      break;

   case MX_Unlocking:
      /* OK - we need to complete the unlock */
      VG_TRACK( post_mutex_unlock, tid, (void *)mutexp );
      mutex_setstate(tid, mx, MX_Free);
      break;

   case MX_Init:
   case MX_Dead:
      vg_assert(0);
   }
}
Пример #12
0
t_error	ia32_thread_stack(i_thread th, t_stack stack)
{
  o_thread* oth;

  if (thread_get(th, &oth) != ERROR_NONE)
    THREAD_LEAVE(thread, ERROR_UNKNOWN);

  oth->machdep.named.ebp = oth->stack - oth->stacksz;
  oth->machdep.named.esp = oth->stack - oth->stacksz;

  return ERROR_NONE;
}
Пример #13
0
/* Try unlocking a lock.  This will move it into a state where it can
   either be unlocked, or change ownership to another thread.  If
   unlock fails, it will remain locked. */
void VG_(tm_mutex_tryunlock)(ThreadId tid, Addr mutexp)
{
   struct thread *th;
   struct mutex *mx;

   mx = mutex_check_initialized(tid, mutexp, "try-unlocking");

   th = thread_get(tid);

   if (th == NULL)
      thread_report(tid, THE_NotExist, "try-unlocking mutex");
   else {
      switch(th->state) {
      case TS_Alive:
      case TS_Running:		/* OK */
	 break;

      case TS_Dead:
      case TS_Zombie:
	 thread_report(tid, THE_NotAlive, "try-unlocking mutex");
	 break;

      case TS_JoinBlocked:
      case TS_CVBlocked:
      case TS_MutexBlocked:
	 thread_report(tid, THE_Blocked, "try-unlocking mutex");
	 do_thread_run(th);
	 break;
      }
   }

   switch(mx->state) {
   case MX_Locked:
      if (mx->owner != tid)
	 mutex_report(tid, mutexp, MXE_NotOwner, "try-unlocking");
      break;

   case MX_Free:
      mutex_report(tid, mutexp, MXE_NotLocked, "try-unlocking");
      break;

   case MX_Unlocking:
      mutex_report(tid, mutexp, MXE_NotLocked, "try-unlocking");
      break;

   case MX_Init:
   case MX_Dead:
      vg_assert(0);
   }

   mutex_setstate(tid, mx, MX_Unlocking);
}
Пример #14
0
void VG_(tm_thread_detach)(ThreadId tid)
{
   struct thread *th = thread_get(tid);

   if (th == NULL)
      thread_report(tid, THE_NotExist, "detaching");
   else {
      if (th->detached)
	 thread_report(tid, THE_Detached, "detaching");
      else {
	 /* XXX look for waiters */
	 th->detached = True;
      }
   }
}
Пример #15
0
t_status	interface_thread_attribute_state(o_syscall*	message)
{
  o_thread*		o;

  if (thread_get(message->u.request.u.thread_attribute_state.arg1, &o) != STATUS_OK)
    {
      message->u.reply.error = STATUS_ERROR;
    }
  else
    {
      message->u.reply.error = STATUS_OK;
      message->u.reply.u.thread_attribute_state.result1 = o->state;
    }

  return (STATUS_OK);
}
Пример #16
0
static void irq_notify(void)
{
    Context* context = get_context();

    uint8_t irq = IRQ(context->num);
    if (!irqThread[irq]) return;

    Thread* receiver = thread_get(irqThread[irq]);
    if (receiver->state == WAIT_RECEIVING && receiver->waitingFor == 0
                                          && receiver->waitingIrq == irq)
    {
        irqPending[irq] = false;
        scheduler_unblock(receiver);
    }
    else
        irqPending[irq] = true;
}
Пример #17
0
static bool _is_iface(kernel_pid_t iface)
{
#ifdef MODULE_NG_NETIF
    kernel_pid_t ifs[NG_NETIF_NUMOF];
    size_t numof = ng_netif_get(ifs);

    for (size_t i = 0; i < numof && i < NG_NETIF_NUMOF; i++) {
        if (ifs[i] == iface) {
            return true;
        }
    }

    return false;
#else
    return (thread_get(iface) != NULL);
#endif
}
Пример #18
0
/* A thread is terminating itself
    - fails if tid has already terminated
    - if detached, tid becomes invalid for all further operations
    - if not detached, the thread remains in a Zombie state until
      someone joins on it
 */
void VG_(tm_thread_exit)(ThreadId tid)
{
   struct thread *th = thread_get(tid);

   if (th == NULL)
      thread_report(tid, THE_NotExist, "exiting");
   else {
      struct thread *joiner;

      switch(th->state) {
      case TS_Dead:
      case TS_Zombie:	/* already exited once */
	 thread_report(tid, THE_NotAlive, "exiting");
	 break;

      case TS_MutexBlocked:
      case TS_CVBlocked:
      case TS_JoinBlocked:
	    thread_report(tid, THE_Blocked, "exiting");
	    break;

      case TS_Alive:
      case TS_Running:
	 /* OK */
	 break;
      }

      /* ugly - walk all threads to find people joining with us */
      /* In pthreads its an error to have multiple joiners, but that
	 seems a bit specific to implement here; there should a way
	 for the thread library binding to handle this. */
      VG_(OSet_ResetIter)(threadSet);
      while ((joiner = VG_(OSet_Next)(threadSet)) != NULL) {
	 if (joiner->state == TS_JoinBlocked && joiner->th_blocked == th) {
	    /* found someone - wake them up */
	    do_thread_run(joiner);

	    /* we're dead */
	    do_thread_dead(th);
	 }
      }

      if (th->state != TS_Dead)
	 do_thread_block_zombie(th);
   }
}
Пример #19
0
void  thread_stack_print(void)
{
    /* Print the current stack to stdout. */

    #if defined(DEVELHELP)
    volatile thread_t* task = thread_get(sched_active_pid);
    if (task) {

        char* stack_top = task->stack_start + task->stack_size;
        int   size = stack_top - task->sp;
        printf("Printing current stack of thread %" PRIkernel_pid "\n", thread_getpid());
        esp_hexdump((void*)(task->sp), size >> 2, 'w', 8);
    }
    #else
    NOT_SUPPORTED();
    #endif
}
Пример #20
0
t_error	ia32_thread_reserve(i_task tsk, i_thread* th)
{
  o_thread *oth;
  ao_thread_named *src;
  o_task* otsk;
  o_as*	oas;

  if (thread_get(*th, &oth) != ERROR_NONE)
    THREAD_LEAVE(thread, ERROR_UNKNOWN);
  src = &(oth->machdep.named);
  if (task_get(oth->taskid, &otsk) != ERROR_NONE)
    TASK_LEAVE(task, ERROR_UNKNOWN);
  if (as_get(otsk->asid, &oas) != ERROR_NONE)
    AS_LEAVE(as, ERROR_UNKNOWN);
  src->cr3 = (t_uint32) oas->machdep.pd;

  return ERROR_NONE;
}
Пример #21
0
/* Add pending read thread. */
struct thread *
thread_add_read_pend (struct lib_globals *zg,
                      int (*func) (struct thread *), void *arg, int val)
{
  struct thread *thread;
  struct thread_master *m = zg->master;

  pal_assert (m != NULL);

  thread = thread_get (zg, THREAD_READ_PEND, func, arg);
  if (thread == NULL)
    return NULL;

  thread->u.val = val;
  thread_list_add (&m->read_pend, thread);

  return thread;
}
Пример #22
0
/* Add low priority event thread. */
struct thread *
thread_add_event_low (struct lib_globals *zg,
                      int (*func) (struct thread *), void *arg, int val)
{
  struct thread *thread;
  struct thread_master *m = zg->master;

  pal_assert (m != NULL);

  thread = thread_get (zg, THREAD_EVENT_LOW, func, arg);
  if (thread == NULL)
    return NULL;

  thread->u.val = val;
  thread_list_add (&m->event_low, thread);

  return thread;
}
Пример #23
0
/* Add simple event thread. */
struct thread *
thread_add_event (struct thread_master *master,
		  int (*func) (struct thread *), void *arg, int val)
{
  struct thread *thread;
  struct thread_master *m = master;

  assert (m != NULL);

  thread = thread_get (m, THREAD_EVENT, func, arg);
  if (thread == NULL)
    return NULL;

  thread->u.val = val;
  thread_list_add (&m->event, thread);

  return thread;
}
Пример #24
0
struct thread *kthread_create(uintptr_t code, int argc, char *argv[])
{
    int tid;
    struct thread *t;

    tid = thread_create(kproc, code, argc, argv,
                        THREAD_CREATEF_NOSTART_THREAD);
    if (tid < 0)
        return NULL;

    t = thread_get(kproc, tid);

    /* XXX: I am not sure this is possible, will see while testing. If this
     * happens it will be worth recovering
     */
    if (!t)
        kernel_panic("Thread get == NULL after thread_create()");

    return t;
}
Пример #25
0
int event_wait(int id, int event) {
	struct thread *thread = thread_get(id);

	if (!thread) {
		return 1;
	}

	if (event < 0) {
		if (irqstate[~event]) {
			return 1;
		}
		return 0;
	}	

	if (event < 0 || event >= EV_COUNT) {
		return 1;
	}

	if (irqstate[event]) {
		thread_save(thread);
		schedule_push(thread);
		thread->state = TS_QUEUED;
	}
	else {
		/* queue thread */
		if (!evqueue[event].back_thread) {
			evqueue[event].front_thread = thread;
		}
		else {
			evqueue[event].back_thread->next_evqueue = thread;
		}
		evqueue[event].back_thread = thread;
		thread->next_evqueue = NULL;
		thread->event = event;

		thread_save(thread);
		thread->state = TS_WAITING;
	}

	return 0;
}
Пример #26
0
/* Wait for a condition, putting thread into blocked state.  Fails if:
    - condp has not been initialized
    - thread doesn't hold mutexp
    - thread is blocked on some other object
    - thread is already blocked on mutex
 */
void VG_(tm_cond_wait)(ThreadId tid, Addr condp, Addr mutexp)
{
   struct thread *th = thread_get(tid);
   struct mutex *mx;
   struct condvar *cv;
   struct condvar_waiter *waiter;

   /* Condvar must exist */
   cv = condvar_check_initialized(tid, condp, "waiting");

   /* Mutex must exist */
   mx = mutex_check_initialized(tid, mutexp, "waiting on condvar");

   /* Thread must own mutex */
   if (mx->state != MX_Locked) {
      mutex_report(tid, mutexp, MXE_NotLocked, "waiting on condvar");
      VG_(tm_mutex_trylock)(tid, mutexp);
      VG_(tm_mutex_acquire)(tid, mutexp);
   } else if (mx->owner != tid) {
      mutex_report(tid, mutexp, MXE_NotOwner, "waiting on condvar");
      mx->owner = tid;
   }

   /* Thread must not be already waiting for condvar */
   waiter = get_waiter(cv, tid);
   if (waiter != NULL)
      condvar_report(tid, condp, CVE_Blocked, "waiting");
   else {
      waiter = VG_(arena_malloc)(VG_AR_CORE, sizeof(*waiter));
      waiter->condvar = cv;
      waiter->mutex = mx;
      waiter->next = cv->waiters;
      cv->waiters = waiter;
   }

   /* Thread is now blocking on condvar */
   do_thread_block_condvar(th, cv);

   /* (half) release mutex */
   VG_(tm_mutex_tryunlock)(tid, mutexp);
}
Пример #27
0
static void thread_report(ThreadId tid, enum thread_error err, const Char *action)
{
   Char *errstr = "?";
   struct thread *th = thread_get(tid);
   struct thread_error_data errdata;

   switch(err) {
   case THE_NotExist:	errstr = "non existent"; break;
   case THE_NotAlive:	errstr = "not alive"; break;
   case THE_Rebirth:	errstr = "re-born"; break;
   case THE_Blocked:	errstr = "blocked"; break;
   case THE_NotBlocked:	errstr = "not blocked"; break;
   case THE_Detached:	errstr = "detached"; break;
   }

   errdata.err = err;
   errdata.th = th;
   errdata.action = action;
   
   VG_(maybe_record_error)(VG_(get_running_tid)(), ThreadErr, 0, errstr, &errdata);
}
Пример #28
0
void send_receive(uint16_t to, uint16_t from)
{
    Thread *sender, *receiver, *current = scheduler_current();

    if (to)
    {
        receiver = thread_get(to);

        if (receiver->state != WAIT_RECEIVING ||
            !(receiver->waitingFor == (uint16_t)-1 ||
              receiver->waitingFor == current->tid))
        {
            if (from)
                return scheduler_wait(to, WAIT_SEND_RECV);
            else
                return scheduler_wait(to, WAIT_SENDING);
        }

        deliver(current, receiver);
        scheduler_unblock(receiver);
    }

    if (from)
    {
        if (!list_empty(&current->waitingList))
        {
            sender = list_item(list_pop(&current->waitingList), Thread, queueLink);
            deliver(sender, current);

            if (sender->state == WAIT_SENDING)
                scheduler_unblock(sender);
            else
                sender->state = WAIT_RECEIVING;
        }
        else
            scheduler_wait(from, WAIT_RECEIVING);
    }

    return;
}
Пример #29
0
int main(void)
{
    puts("START");

    kernel_pid_t pid = thread_create(stack,
                  sizeof(stack),
                  THREAD_PRIORITY_MAIN - 1,
                  THREAD_CREATE_STACKTEST,
                  _thread,
                  NULL,
                  "second_thread");

    thread_t *thread = (thread_t*) thread_get(pid);
    _set(thread, 0x1);
    _set(thread, 0x64);
    _set(thread, 0x1);
    _set(thread, 0x8);
    _set(thread, 0x2);
    _set(thread, 0x4);

    while(!done) {};

    puts("main: setting 100ms timeout...");
    xtimer_t t;
    uint32_t before = xtimer_now_usec();
    xtimer_set_timeout_flag(&t, TIMEOUT);
    thread_flags_wait_any(THREAD_FLAG_TIMEOUT);
    uint32_t diff = xtimer_now_usec() - before;
    printf("main: timeout triggered. time passed: %uus\n", (unsigned)diff);

    if (diff < (TIMEOUT + THRESHOLD)) {
        puts("SUCCESS");
        return 0;
    }
    puts("FAILURE");

    return 1;
}
Пример #30
0
/* Add timer event thread. */
struct thread *
thread_add_timer_timeval (struct lib_globals *zg,
                          int (*func) (struct thread *), void *arg,
                          struct pal_timeval timer)
{
  struct thread_master *m = zg->master;
  struct pal_timeval timer_now;
  struct thread *thread;

  pal_assert (m != NULL);

  thread = thread_get (zg, THREAD_TIMER, func, arg);
  if (thread == NULL)
    return NULL;

  /* Do we need jitter here? */
  pal_time_tzcurrent (&timer_now, NULL);
  timer_now.tv_sec += timer.tv_sec;
  timer_now.tv_usec += timer.tv_usec;
  while (timer_now.tv_usec >= TV_USEC_PER_SEC)
    {
      timer_now.tv_sec++;
      timer_now.tv_usec -= TV_USEC_PER_SEC;
    }

  /* Correct negative value.  */
  if (timer_now.tv_sec < 0)
    timer_now.tv_sec = PAL_TIME_MAX_TV_SEC;
  if (timer_now.tv_usec < 0)
    timer_now.tv_usec = PAL_TIME_MAX_TV_USEC;

  thread->u.sands = timer_now;

  /* Common process.  */
  thread_add_timer_common (m, thread);

  return thread;
}