void alarmSchedule(Alarm_t *alarm, uint32_t milliseconds) { // we want to avoid inserting local variables in the global alarm list // (but this warning, not an error, because the user function may never return) WARN_ON(isStackAddress(alarm)); // PRINTF("alarmSchedule %p, ms=%lu\n", alarm, milliseconds); alarm->jiffies = (uint32_t)getJiffies() + milliseconds; // locking is required, because both kernel and user threads can be using this function Handle_t h; ATOMIC_START(h); // unschedule the alarm, if it was already scheduled SLIST_REMOVE_SAFE(&alarmListHead, alarm, Alarm_s, chain); // insert it in appropriate position Alarm_t **prev = &SLIST_FIRST(&alarmListHead); Alarm_t *a = *prev; while (a && timeAfter32(alarm->jiffies, a->jiffies)) { prev = &SLIST_NEXT(a, chain); a = *prev; } SLIST_INSERT(prev, alarm, chain); #if USE_THREADS // always reschedule alarm processing in case some alarm was added // that might need to be processed before end of current kernel sleep time processFlags.bits.alarmsProcess = true; // and make sure the kernel thread is awake and ready to deal with it threadWakeup(KERNEL_THREAD_INDEX, THREAD_READY); #endif ATOMIC_END(h); }
int vtSleep(VtRendez *q) { Thread *s, *t, *tt; VtLock *p; p = q->lk; lock(&p->lk); s = *vtRock; /* * venti currently contains code that assume locks can be passed between threads :-( * assert(p->writer != s); */ assert(p->writer != nil); assert(p->readers == 0); t = p->qfirst; if(t == nil) { p->writer = nil; } else if(t->state == QueuingW) { p->qfirst = t->next; p->writer = t; threadWakeup(t); } else { p->writer = nil; while(t != nil && t->state == QueuingR) { tt = t; t = t->next; p->readers++; threadWakeup(tt); } } if(q->wfirst == nil) q->wfirst = s; else q->wlast->next = s; q->wlast = s; s->next = nil; unlock(&p->lk); threadSleep(s); assert(p->writer == s); return 1; }
void vtUnlock(VtLock *p) { Thread *t, *tt; lock(&p->lk); /* * venti currently has code that assumes lock can be passed between threads :-) * assert(p->writer == *vtRock); */ assert(p->writer != nil); assert(p->readers == 0); t = p->qfirst; if(t == nil) { p->writer = nil; unlock(&p->lk); return; } if(t->state == QueuingW) { p->qfirst = t->next; p->writer = t; unlock(&p->lk); threadWakeup(t); return; } p->writer = nil; while(t != nil && t->state == QueuingR) { tt = t; t = t->next; p->readers++; threadWakeup(tt); } p->qfirst = t; unlock(&p->lk); }
void vtRUnlock(VtLock *p) { Thread *t; lock(&p->lk); assert(p->writer == nil && p->readers > 0); p->readers--; t = p->qfirst; if(p->readers > 0 || t == nil) { unlock(&p->lk); return; } assert(t->state == QueuingW); p->qfirst = t->next; p->writer = t; unlock(&p->lk); threadWakeup(t); }