Skip to content

Commit 149d1d4

Browse files
committed
core: Add a test for blocking in native code
1 parent 35ba971 commit 149d1d4

File tree

3 files changed

+114
-0
lines changed

3 files changed

+114
-0
lines changed

src/libcore/task.rs

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -504,6 +504,74 @@ mod tests {
504504
comm::recv(po);
505505
}
506506

507+
#[nolink]
508+
native mod rt {
509+
fn rust_dbg_lock_create() -> *ctypes::void;
510+
fn rust_dbg_lock_destroy(lock: *ctypes::void);
511+
fn rust_dbg_lock_lock(lock: *ctypes::void);
512+
fn rust_dbg_lock_unlock(lock: *ctypes::void);
513+
fn rust_dbg_lock_wait(lock: *ctypes::void);
514+
fn rust_dbg_lock_signal(lock: *ctypes::void);
515+
}
516+
517+
#[test]
518+
fn spawn_sched_blocking() {
519+
520+
// Testing that a task in one scheduler can block natively
521+
// without affecting other schedulers
522+
iter::repeat(20u) {||
523+
524+
let start_po = comm::port();
525+
let start_ch = comm::chan(start_po);
526+
let fin_po = comm::port();
527+
let fin_ch = comm::chan(fin_po);
528+
529+
let lock = rt::rust_dbg_lock_create();
530+
531+
spawn_sched(1u) {||
532+
rt::rust_dbg_lock_lock(lock);
533+
534+
comm::send(start_ch, ());
535+
536+
// Block the scheduler thread
537+
rt::rust_dbg_lock_wait(lock);
538+
rt::rust_dbg_lock_unlock(lock);
539+
540+
comm::send(fin_ch, ());
541+
};
542+
543+
// Wait until the other task has its lock
544+
comm::recv(start_po);
545+
546+
fn pingpong(po: comm::port<int>, ch: comm::chan<int>) {
547+
let val = 20;
548+
while val > 0 {
549+
val = comm::recv(po);
550+
comm::send(ch, val - 1);
551+
}
552+
}
553+
554+
let setup_po = comm::port();
555+
let setup_ch = comm::chan(setup_po);
556+
let parent_po = comm::port();
557+
let parent_ch = comm::chan(parent_po);
558+
spawn {||
559+
let child_po = comm::port();
560+
comm::send(setup_ch, comm::chan(child_po));
561+
pingpong(child_po, parent_ch);
562+
};
563+
564+
let child_ch = comm::recv(setup_po);
565+
comm::send(child_ch, 20);
566+
pingpong(parent_po, child_ch);
567+
rt::rust_dbg_lock_lock(lock);
568+
rt::rust_dbg_lock_signal(lock);
569+
rt::rust_dbg_lock_unlock(lock);
570+
comm::recv(fin_po);
571+
rt::rust_dbg_lock_destroy(lock);
572+
}
573+
}
574+
507575
}
508576

509577

src/rt/rust_builtin.cpp

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -626,6 +626,46 @@ rust_log_console_off() {
626626
log_console_off(task->kernel->env);
627627
}
628628

629+
extern "C" CDECL lock_and_signal *
630+
rust_dbg_lock_create() {
631+
return new lock_and_signal();
632+
}
633+
634+
extern "C" CDECL void
635+
rust_dbg_lock_destroy(lock_and_signal *lock) {
636+
rust_task *task = rust_task_thread::get_task();
637+
I(task->thread, lock);
638+
delete lock;
639+
}
640+
641+
extern "C" CDECL void
642+
rust_dbg_lock_lock(lock_and_signal *lock) {
643+
rust_task *task = rust_task_thread::get_task();
644+
I(task->thread, lock);
645+
lock->lock();
646+
}
647+
648+
extern "C" CDECL void
649+
rust_dbg_lock_unlock(lock_and_signal *lock) {
650+
rust_task *task = rust_task_thread::get_task();
651+
I(task->thread, lock);
652+
lock->unlock();
653+
}
654+
655+
extern "C" CDECL void
656+
rust_dbg_lock_wait(lock_and_signal *lock) {
657+
rust_task *task = rust_task_thread::get_task();
658+
I(task->thread, lock);
659+
lock->wait();
660+
}
661+
662+
extern "C" CDECL void
663+
rust_dbg_lock_signal(lock_and_signal *lock) {
664+
rust_task *task = rust_task_thread::get_task();
665+
I(task->thread, lock);
666+
lock->signal();
667+
}
668+
629669
//
630670
// Local Variables:
631671
// mode: C++

src/rt/rustrt.def.in

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,3 +100,9 @@ rust_uvtmp_read_start
100100
rust_uvtmp_timer
101101
rust_uvtmp_delete_buf
102102
rust_uvtmp_get_req_id
103+
rust_dbg_lock_create
104+
rust_dbg_lock_destroy
105+
rust_dbg_lock_lock
106+
rust_dbg_lock_unlock
107+
rust_dbg_lock_wait
108+
rust_dbg_lock_signal

0 commit comments

Comments
 (0)