void thinkos_ev_wait_svc(int32_t * arg) { unsigned int wq = arg[0]; unsigned int no = wq - THINKOS_EVENT_BASE; int self = thinkos_rt.active; unsigned int ev; #if THINKOS_ENABLE_ARG_CHECK if (no >= THINKOS_EVENT_MAX) { DCC_LOG1(LOG_ERROR, "object %d is not an event set!", wq); arg[0] = THINKOS_EINVAL; return; } #if THINKOS_ENABLE_EVENT_ALLOC if (__bit_mem_rd(&thinkos_rt.ev_alloc, no) == 0) { DCC_LOG1(LOG_ERROR, "invalid event set %d!", wq); arg[0] = THINKOS_EINVAL; return; } #endif #endif cm3_cpsid_i(); /* check for any pending unmasked event */ if ((ev = __clz(__rbit(thinkos_rt.ev[no].pend & thinkos_rt.ev[no].mask))) < 32) { DCC_LOG2(LOG_MSG, "set=0x%08x msk=0x%08x", thinkos_rt.ev[no].pend, thinkos_rt.ev[no].mask); __bit_mem_wr(&thinkos_rt.ev[no].pend, ev, 0); DCC_LOG2(LOG_INFO, "pending event %d.%d!", wq, ev); arg[0] = ev; cm3_cpsie_i(); return; } /* insert into the wait queue */ __thinkos_wq_insert(wq, self); /* wait for event */ /* remove from the ready wait queue */ __bit_mem_wr(&thinkos_rt.wq_ready, thinkos_rt.active, 0); #if THINKOS_ENABLE_TIMESHARE /* if the ready queue is empty, collect the threads from the CPU wait queue */ if (thinkos_rt.wq_ready == 0) { thinkos_rt.wq_ready = thinkos_rt.wq_tmshare; thinkos_rt.wq_tmshare = 0; } #endif cm3_cpsie_i(); DCC_LOG2(LOG_INFO, "<%d> waiting for event %d.xx ...", self, wq); /* signal the scheduler ... */ __thinkos_defer_sched(); }
void thinkos_sem_wait_svc(int32_t * arg) { unsigned int wq = arg[0]; unsigned int sem = wq - THINKOS_SEM_BASE; int self = thinkos_rt.active; #if THINKOS_ENABLE_ARG_CHECK if (sem >= THINKOS_SEMAPHORE_MAX) { DCC_LOG1(LOG_ERROR, "object %d is not a semaphore!", wq); arg[0] = THINKOS_EINVAL; return; } #if THINKOS_ENABLE_SEM_ALLOC if (__bit_mem_rd(thinkos_rt.sem_alloc, sem) == 0) { DCC_LOG1(LOG_ERROR, "invalid semaphore %d!", wq); arg[0] = THINKOS_EINVAL; return; } #endif #endif arg[0] = 0; /* avoid possible race condition on sem_val */ /* this is only necessary in case we use the __uthread_sem_post() call inside interrupt handlers */ /* TODO: study the possibility of using exclusive access instead of disabling interrupts. */ cm3_cpsid_i(); if (thinkos_rt.sem_val[sem] > 0) { thinkos_rt.sem_val[sem]--; /* reenable interrupts ... */ cm3_cpsie_i(); return; } /* insert into the semaphore wait queue */ __thinkos_wq_insert(wq, self); DCC_LOG2(LOG_INFO, "<%d> waiting on semaphore %d...", self, wq); /* wait for event */ /* remove from the ready wait queue */ __bit_mem_wr(&thinkos_rt.wq_ready, self, 0); #if THINKOS_ENABLE_TIMESHARE /* if the ready queue is empty, collect the threads from the CPU wait queue */ if (thinkos_rt.wq_ready == 0) { thinkos_rt.wq_ready = thinkos_rt.wq_tmshare; thinkos_rt.wq_tmshare = 0; } #endif /* reenable interrupts ... */ cm3_cpsie_i(); /* signal the scheduler ... */ __thinkos_defer_sched(); }
void isink_test(void) { unsigned int pre; unsigned int pulse; int mode; pre = 500; pulse = 1000; /* disable interrupts */ cm3_cpsid_i(); for (mode = 0; mode < 26; ++mode) { isink_io_cfg(mode); isink_pulse(pre, pulse); udelay(pulse + 500); } cm3_cpsie_i(); isink_drv.mode = -1; }
void cm3_udelay_calibrate(void) { struct cm3_systick * systick = CM3_SYSTICK; uint32_t ticks1ms; uint32_t rvr; uint32_t csr; cm3_cpsid_i(); rvr = systick->rvr; csr = systick->csr; systick->rvr = 0x00ffffff; systick->csr = SYSTICK_CSR_ENABLE; ticks1ms = cm3_systick_load_1ms << 8; udelay_calibrate(ticks1ms, cm3_get_ticks); systick->rvr = rvr; systick->csr = csr; cm3_cpsie_i(); }
void thinkos_sem_post_svc(int32_t * arg) { unsigned int wq = arg[0]; unsigned int sem = wq - THINKOS_SEM_BASE; int th; #if THINKOS_ENABLE_ARG_CHECK if (sem >= THINKOS_SEMAPHORE_MAX) { DCC_LOG1(LOG_ERROR, "object %d is not a semaphore!", wq); arg[0] = THINKOS_EINVAL; return; } #if THINKOS_ENABLE_SEM_ALLOC if (__bit_mem_rd(thinkos_rt.sem_alloc, sem) == 0) { DCC_LOG1(LOG_ERROR, "invalid semaphore %d!", wq); arg[0] = THINKOS_EINVAL; return; } #endif #endif arg[0] = 0; cm3_cpsid_i(); if ((th = __thinkos_wq_head(wq)) == THINKOS_THREAD_NULL) { /* no threads waiting on the semaphore, increment. */ thinkos_rt.sem_val[sem]++; } else { /* wakeup from the sem wait queue */ __thinkos_wakeup(wq, th); DCC_LOG2(LOG_INFO, "<%d> wakeup from sem %d ", th, wq); /* signal the scheduler ... */ __thinkos_defer_sched(); } cm3_cpsie_i(); }
void thinkos_sem_trywait_svc(int32_t * arg) { unsigned int wq = arg[0]; unsigned int sem = wq - THINKOS_SEM_BASE; #if THINKOS_ENABLE_ARG_CHECK if (sem >= THINKOS_SEMAPHORE_MAX) { DCC_LOG1(LOG_ERROR, "object %d is not a semaphore!", wq); arg[0] = THINKOS_EINVAL; return; } #if THINKOS_ENABLE_SEM_ALLOC if (__bit_mem_rd(thinkos_rt.sem_alloc, sem) == 0) { DCC_LOG1(LOG_ERROR, "invalid semaphore %d!", wq); arg[0] = THINKOS_EINVAL; return; } #endif #endif /* avoid possible race condition on sem_val */ /* this is only necessary in case we use the __uthread_sem_post() call inside interrupt handlers */ /* TODO: study the possibility of using exclusive access instead of disabling interrupts. */ cm3_cpsid_i(); if (thinkos_rt.sem_val[sem] > 0) { thinkos_rt.sem_val[sem]--; arg[0] = 0; } else { arg[0] = THINKOS_EAGAIN; } cm3_cpsie_i(); }
void thinkos_ev_unmask_svc(int32_t * arg) { unsigned int wq = arg[0]; uint32_t mask = arg[1]; unsigned int no = wq - THINKOS_EVENT_BASE; unsigned int ev; int th; #if THINKOS_ENABLE_ARG_CHECK if (no >= THINKOS_EVENT_MAX) { DCC_LOG1(LOG_ERROR, "object %d is not an event set!", wq); arg[0] = THINKOS_EINVAL; return; } #if THINKOS_ENABLE_EVENT_ALLOC if (__bit_mem_rd(&thinkos_rt.ev_alloc, no) == 0) { DCC_LOG1(LOG_ERROR, "invalid event set %d!", wq); arg[0] = THINKOS_EINVAL; return; } #endif #endif cm3_cpsid_i(); /* unmask the events on the mask bitmap */ thinkos_rt.ev[no].mask |= mask; /* wake up the first unmasked thread if any. */ if ((ev = __clz(__rbit(thinkos_rt.ev[no].pend & mask))) < 32) { if ((th = __thinkos_wq_head(wq)) != THINKOS_THREAD_NULL) { /* a pending event was unmaksed and there is a thread waiting on the queue, clear the event pending flag and wakes up the thread. */ __bit_mem_wr(&thinkos_rt.ev[no].pend, ev, 0); /* wakeup from the event wait queue, set the return of the thread to the event */ __thinkos_wakeup_return(wq, th, ev); DCC_LOG3(LOG_TRACE, "<%d> waked up with event %d.%d", th, wq, ev); /* signal the scheduler ... */ __thinkos_defer_sched(); } else { /* no threads waiting */ cm3_cpsie_i(); return; } } /* wake up as many other threads as possible */ while ((ev = __clz(__rbit(thinkos_rt.ev[no].pend & mask))) < 32) { if ((th = __thinkos_wq_head(wq)) != THINKOS_THREAD_NULL) { /* a pending event was unmaksed and there is a thread waiting on the queue, clear the event pending flag and wakes up the thread. */ __bit_mem_wr(&thinkos_rt.ev[no].pend, ev, 0); /* wakeup from the event wait queue, set the return of the thread to the event */ __thinkos_wakeup_return(wq, th, ev); DCC_LOG3(LOG_TRACE, "<%d> waked up with event %d.%d", th, wq, ev); } else { /* no more threads waiting */ break; } } cm3_cpsie_i(); }
void thinkos_ev_timedwait_svc(int32_t * arg) { unsigned int wq = arg[0]; uint32_t ms = (uint32_t)arg[1]; unsigned int no = wq - THINKOS_EVENT_BASE; int self = thinkos_rt.active; unsigned int ev; #if THINKOS_ENABLE_ARG_CHECK if (no >= THINKOS_EVENT_MAX) { DCC_LOG1(LOG_ERROR, "object %d is not an event set!", wq); arg[0] = THINKOS_EINVAL; return; } #if THINKOS_ENABLE_EVENT_ALLOC if (__bit_mem_rd(&thinkos_rt.ev_alloc, no) == 0) { DCC_LOG1(LOG_ERROR, "invalid event set %d!", wq); arg[0] = THINKOS_EINVAL; return; } #endif #endif cm3_cpsid_i(); /* check for any pending unmasked event */ if ((ev = __clz(__rbit(thinkos_rt.ev[no].pend & thinkos_rt.ev[no].mask))) < 32) { __bit_mem_wr(&thinkos_rt.ev[no].pend, ev, 0); arg[0] = ev; cm3_cpsie_i(); return; } /* insert into the mutex wait queue */ __thinkos_tmdwq_insert(wq, self, ms); /* wait for event */ /* remove from the ready wait queue */ __bit_mem_wr(&thinkos_rt.wq_ready, thinkos_rt.active, 0); #if THINKOS_ENABLE_TIMESHARE /* if the ready queue is empty, collect the threads from the CPU wait queue */ if (thinkos_rt.wq_ready == 0) { thinkos_rt.wq_ready = thinkos_rt.wq_tmshare; thinkos_rt.wq_tmshare = 0; } #endif /* Set the default return value to timeout. The ev_rise() call will change it to the active event */ arg[0] = THINKOS_ETIMEDOUT; cm3_cpsie_i(); DCC_LOG2(LOG_INFO, "<%d> waiting for event %d...", self, wq); /* signal the scheduler ... */ __thinkos_defer_sched(); }