Skip to content

Commit

Permalink
timeout for waiting
Browse files Browse the repository at this point in the history
  • Loading branch information
1vnt committed Jan 26, 2025
1 parent 47daf13 commit 0feb524
Show file tree
Hide file tree
Showing 11 changed files with 147 additions and 21 deletions.
5 changes: 4 additions & 1 deletion kernel/arch/x86_64/apic.c
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ static void apic_timer_calibrate()
}

uint64_t avg = sum / (wait_ms * runs);
avg = (avg+100000) / 100000 * 100000;
avg = (avg + 100000) / 100000 * 100000;
curcpu()->md.lapic_ticks_per_ms = avg;
printk(LOG_DBG "apic timer: %ld ticks/ms\n",
curcpu()->md.lapic_ticks_per_ms);
Expand All @@ -130,6 +130,9 @@ static int apic_timer_handler(IrqObj *obj, Context *ctx, void *private)

void apic_arm(uint64_t delta_us)
{
#if 0
printk("next timer in %ld ms\n", delta_us / 1000);
#endif
if (delta_us == 0) {
apic_write(APIC_REG_TIMER_INITIAL, 0);
return;
Expand Down
4 changes: 3 additions & 1 deletion kernel/include/ivy-internal/sched.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#pragma once

#include "ivy/status.h"
#include <sys/queue.h>
#include "ivy/cpudata.h"
#include "ivy/object.h"
Expand All @@ -16,6 +17,7 @@ void sched_preempt(CpuData *data);
void sched_yield(Thread *thread, CpuData *data);

void sched_unwait_thread(Thread *thread, int status, int boost);
int sched_wait_thread(Thread *thread, int hastimeout);

OsStatus sched_wait_thread(Thread *thread, int hastimeout);

void sched_internal_ready(Thread *thread);
12 changes: 9 additions & 3 deletions kernel/include/ivy/sched.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#pragma once

#include "ivy/status.h"
#include <sys/queue.h>
#include "ivy/dpc.h"
#include "ivy/timer.h"
Expand Down Expand Up @@ -56,6 +57,9 @@ typedef struct thread {
WaitBlock *wait_block_table;
WaitBlock thread_wait_blocks[THREAD_WAIT_BLOCKS];

Timer timeout;
WaitBlock timeout_wait_block;

TAILQ_ENTRY(thread) entry;
} Thread;

Expand Down Expand Up @@ -100,7 +104,9 @@ void sched_exit_self();

Thread *sched_satisfy_object(ObjHeader *object, int boost, int all, int status);

int sched_wait_multi(int waitmode, time_t timeout_ms, size_t objcount,
ObjHeader **objtable, WaitBlock *wbtable);
#define TIMEOUT_NONE 0

int sched_wait(int waitmode, time_t timeout_ms, ObjHeader *obj);
OsStatus sched_wait_multi(int waitmode, time_t timeout_ms, size_t objcount,
ObjHeader **objtable, WaitBlock *wbtable);
OsStatus sched_wait(int waitmode, time_t timeout_ms, ObjHeader *obj);
OsStatus sleep(int waitmode, time_t ms);
3 changes: 3 additions & 0 deletions kernel/include/ivy/status.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,7 @@ enum {
IVY_NOSUPPORT,
IVY_NOSPACE,
IVY_INUSE,
IVY_WAIT_TIMEOUT,
};

typedef int OsStatus;
1 change: 1 addition & 0 deletions kernel/include/ivy/timer.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,3 +41,4 @@ void timer_init(Timer *timer, Dpc *dpc);
void timer_reset(Timer *timer, Timespec deadline);
void timer_reset_add(Timer *timer, time_t ms);
void timer_install(Timer *timer, void *ctx);
void timer_uninstall(Timer *timer);
10 changes: 7 additions & 3 deletions kernel/src/init.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#include "ivy/kmem.h"
#include "ivy/log.h"
#include "ivy/sched.h"
#include "ivy/status.h"
#include "ivy/timer.h"
#include "ivy/vm.h"
#include "ivy/percpu.h"
Expand Down Expand Up @@ -39,7 +40,7 @@ void print_loop(void *ctx)
{
int cnt = 0;
for (;;) {
printk("%s", (const char *)ctx);
///printk("%s", (const char *)ctx);
if (++cnt == 5)
sched_exit_self();
}
Expand All @@ -62,10 +63,13 @@ void kmain_thread(void *)

Timer timer;
timer_init(&timer, NULL);
timer_reset_add(&timer, 500);
timer_reset_add(&timer, 2000);
timer_install(&timer, NULL);

sched_wait(0, 0, &timer.hdr);
for (;;) {
sleep(0, 500);
}
timer_uninstall(&timer);

printk(LOG_INFO "timer has fired, exit from wait\n");

Expand Down
1 change: 1 addition & 0 deletions kernel/src/irq/softint.c
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#include "ivy/ipl.h"
#include "ivy/softint.h"
#include "ivy-internal/sched.h"
#include "ivy/log.h"

#define PENDING(irql) ((1 << ((irql) - 1)))

Expand Down
6 changes: 4 additions & 2 deletions kernel/src/sched/sched.c
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#include "ivy/log.h"
#include <assert.h>
#include <sys/queue.h>
#include "ivy/dpc.h"
Expand Down Expand Up @@ -161,9 +162,10 @@ void sched_ready(Thread *thread)

void sched_yield(Thread *current, CpuData *data)
{
Ipl ipl = spinlock_acquire(&data->sched.rq_lock);
assert(spinlock_held(&current->lock));
spinlock_acquire_elevated(&data->sched.rq_lock);
Thread *next = next_thread(&data->sched, 0);
spinlock_release(&data->sched.rq_lock, ipl);
spinlock_release_elevated(&data->sched.rq_lock);

if (next) {
sched_switch(current, next);
Expand Down
8 changes: 8 additions & 0 deletions kernel/src/sched/thread.c
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
#include "ivy/status.h"
#include <assert.h>
#include "ivy/timer.h"
#include "ivy/sched.h"
#include "ivy-internal/sched.h"
#include "ivy/vm.h"
Expand All @@ -15,6 +17,12 @@ void thread_init(Thread *thread, ThreadEntryFn entry, int priority,
thread->timeslice_ms = 15;
SPINLOCK_INIT(&thread->lock);

timer_init(&thread->timeout, NULL);

thread->timeout_wait_block.object = &thread->timeout.hdr;
thread->timeout_wait_block.wake_status = IVY_WAIT_TIMEOUT;
thread->timeout_wait_block.thread = thread;

context_init(thread, 0, entry, context);
}

Expand Down
111 changes: 104 additions & 7 deletions kernel/src/sched/wait.c
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/

#include "ivy/log.h"
#include "ivy/status.h"
#include "ivy/timer.h"
#include <assert.h>
#include <stddef.h>
#include "ivy/cpudata.h"
Expand All @@ -56,7 +59,7 @@ static void dequeue_waitblock(WaitBlock *waitblock)
spinlock_release_elevated(&object->obj_lock);
}

int sched_wait_thread(Thread *thread, int hastimeout)
OsStatus sched_wait_thread(Thread *thread, int hastimeout)
{
assert(spinlock_held(&thread->lock));
CpuData *data = curcpu();
Expand All @@ -75,7 +78,11 @@ int sched_wait_thread(Thread *thread, int hastimeout)
wb++;
}

assert(hastimeout == 0);
if (hastimeout) {
wb = &thread->timeout_wait_block;
dequeue_waitblock(wb);
timer_uninstall(&thread->timeout);
}

// thread lock dropped, still IPL@DISPATCH

Expand Down Expand Up @@ -104,9 +111,13 @@ void sched_unwait_thread(Thread *thread, int status, int boost)
wb++;
}

thread->timeout_wait_block.flags |= WB_UNWAITED;

// NOTE: could do quantum stuff

sched_internal_ready(thread);
if (thread->status == THREAD_WAITING) {
sched_internal_ready(thread);
}
}

Thread *sched_satisfy_object(ObjHeader *object, int boost, int all, int status)
Expand Down Expand Up @@ -141,8 +152,8 @@ Thread *sched_satisfy_object(ObjHeader *object, int boost, int all, int status)
return NULL;
}

int sched_wait_multi(int waitmode, time_t timeout_ms, size_t objcount,
ObjHeader **objtable, WaitBlock *wbtable)
OsStatus sched_wait_multi(int waitmode, time_t timeout_ms, size_t objcount,
ObjHeader **objtable, WaitBlock *wbtable)
{
assert(objcount > 0 && objcount < 255);
Thread *thread = curthread();
Expand All @@ -164,6 +175,9 @@ int sched_wait_multi(int waitmode, time_t timeout_ms, size_t objcount,

assert(curipl() < IPL_DISPATCH);
Ipl ipl = ripl(IPL_DISPATCH);

thread->timeout_wait_block.flags = 0;

thread->wait_mode = waitmode;
thread->wait_ipl = ipl;

Expand All @@ -178,6 +192,7 @@ int sched_wait_multi(int waitmode, time_t timeout_ms, size_t objcount,
size_t i;
int status;
ObjHeader *obj;
Timer *timer;

for (i = 0; i < objcount; i++) {
obj = objtable[i];
Expand Down Expand Up @@ -209,13 +224,26 @@ int sched_wait_multi(int waitmode, time_t timeout_ms, size_t objcount,
spinlock_release_elevated(&obj->obj_lock);
}

assert(!timeout_ms);
if (timeout_ms) {
WaitBlock *wb = &thread->timeout_wait_block;
timer = &thread->timeout;

TAILQ_INSERT_TAIL(&timer->hdr.waiter_list, wb, entry);
timer->hdr.waiter_count = 1;

timer_reset_add(timer, timeout_ms);
timer_install(timer, NULL);
}

spinlock_acquire_elevated(&thread->lock);

if (thread->wait_attempt == THREAD_WAIT_ABORTED) {
spinlock_release_elevated(&thread->lock);
if (timeout_ms) {
WaitBlock *wb = &thread->timeout_wait_block;
timer = &thread->timeout;
timer_uninstall(timer);
TAILQ_REMOVE(&timer->hdr.waiter_list, wb, entry);
}

status = thread->wait_status;
Expand All @@ -231,7 +259,7 @@ int sched_wait_multi(int waitmode, time_t timeout_ms, size_t objcount,
return status;
}

int sched_wait(int waitmode, time_t timeout_ms, ObjHeader *obj)
OsStatus sched_wait(int waitmode, time_t timeout_ms, ObjHeader *obj)
{
Thread *thread = curthread();
WaitBlock singlewaitblock;
Expand All @@ -245,6 +273,7 @@ int sched_wait(int waitmode, time_t timeout_ms, ObjHeader *obj)

assert(curipl() < IPL_DISPATCH);
Ipl ipl = ripl(IPL_DISPATCH);
thread->timeout_wait_block.flags = 0;
thread->wait_mode = waitmode;
thread->wait_ipl = ipl;
thread->wait_block_table = NULL;
Expand Down Expand Up @@ -272,11 +301,28 @@ int sched_wait(int waitmode, time_t timeout_ms, ObjHeader *obj)
obj->waiter_count += 1;
spinlock_release_elevated(&obj->obj_lock);

if (timeout_ms) {
WaitBlock *wb = &thread->timeout_wait_block;
Timer *timer = &thread->timeout;
TAILQ_INSERT_TAIL(&timer->hdr.waiter_list, wb, entry);
timer->hdr.waiter_count = 1;

timer_reset_add(timer, timeout_ms);
timer_install(timer, NULL);
}

spinlock_acquire_elevated(&thread->lock);

if (thread->wait_attempt == THREAD_WAIT_ABORTED) {
spinlock_release_elevated(&thread->lock);

if (timeout_ms) {
WaitBlock *wb = &thread->timeout_wait_block;
Timer *timer = &thread->timeout;
timer_uninstall(timer);
TAILQ_REMOVE(&timer->hdr.waiter_list, wb, entry);
}

status = thread->wait_status;
dequeue_waitblock(&singlewaitblock);
thread->wait_attempt = THREAD_WAIT_NONE;
Expand All @@ -294,3 +340,54 @@ int sched_wait(int waitmode, time_t timeout_ms, ObjHeader *obj)

return status;
}

OsStatus sleep(int waitmode, time_t ms)
{
Thread *thread = curthread();

retry:

assert(curipl() < IPL_DISPATCH);
Ipl ipl = ripl(IPL_DISPATCH);
thread->timeout_wait_block.flags = 0;
thread->wait_mode = waitmode;
thread->wait_ipl = ipl;
thread->wait_block_table = NULL;
thread->wait_count = 0;
spinlock_acquire_elevated(&thread->lock);
// NOTE: check for all kinds of stuff here
thread->wait_attempt = THREAD_WAIT_TRY;
spinlock_release_elevated(&thread->lock);

OsStatus status = 0;

WaitBlock *wb = &thread->timeout_wait_block;
Timer *timer = &thread->timeout;
TAILQ_INSERT_TAIL(&timer->hdr.waiter_list, wb, entry);
timer->hdr.waiter_count = 1;
timer_reset_add(timer, ms);
timer_install(timer, NULL);

spinlock_acquire_elevated(&thread->lock);

if (thread->wait_attempt == THREAD_WAIT_ABORTED) {
spinlock_release_elevated(&thread->lock);

timer_uninstall(timer);
TAILQ_REMOVE(&timer->hdr.waiter_list, wb, entry);

status = thread->wait_status;
thread->wait_attempt = THREAD_WAIT_NONE;

xipl(ipl);
return status;
}

thread->wait_attempt = THREAD_WAIT_COMMITTED;

status = sched_wait_thread(thread, 1);

xipl(ipl);

return status;
}
7 changes: 3 additions & 4 deletions kernel/src/time/timer.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,13 @@
#include "ivy/cpudata.h"
#include "ivy/dpc.h"
#include "ivy/heap.h"
#include "ivy/log.h"
#include "ivy/object.h"
#include "ivy/time.h"
#include "ivy/timespec.h"

static int timer_cmp(Timer *a, Timer *b)
{
return timespec_cmp(a->deadline, b->deadline) == 1;
return timespec_cmp(a->deadline, b->deadline) < 0;
}

HEAP_IMPL(timerlist, timer, entry, timer_cmp);
Expand All @@ -36,7 +35,7 @@ void timer_init(Timer *timer, Dpc *dpc)
HEAP_ENTRY_INIT(timer, entry);
}

void timer_uninstall(Timer *timer, int flags)
void timer_uninstall(Timer *timer)
{
TimerEngine *engine = timer->engine;
if (engine) {
Expand All @@ -60,7 +59,7 @@ void timer_reset(Timer *timer, Timespec deadline)
Ipl ipl = spinlock_acquire(&timer->hdr.obj_lock);
if (timer->state == TIMER_QUEUED) {
spinlock_release(&timer->hdr.obj_lock, ipl);
timer_uninstall(timer, 0);
timer_uninstall(timer);
ipl = spinlock_acquire(&timer->hdr.obj_lock);
}
timer->deadline = deadline;
Expand Down

0 comments on commit 0feb524

Please sign in to comment.