Skip to content

Commit

Permalink
thread_yield() possible to return error_number obtained from thread_i…
Browse files Browse the repository at this point in the history
…nterrupt()
  • Loading branch information
lihuiba committed Sep 14, 2024
1 parent 33252d3 commit 6f577f3
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 19 deletions.
2 changes: 1 addition & 1 deletion common/lockfree_queue.h
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ struct ThreadPause : PauseBase {
};

namespace photon {
void thread_yield();
int thread_yield();
}
struct PhotonPause : PauseBase {
inline static __attribute__((always_inline)) void pause() {
Expand Down
47 changes: 31 additions & 16 deletions thread/thread.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1167,41 +1167,44 @@ R"(
return (states) th->state;
}

void thread_yield()
int thread_yield()
{
assert(!AtomicRunQ().single());
auto sw = AtomicRunQ().goto_next();
RunQ rq;
if_update_now();
rq.current->error_number = 0;
auto sw = AtomicRunQ(rq).goto_next();
switch_context(sw.from, sw.to);
return rq.current->error_number;
}

void thread_yield_fast() {
assert(!AtomicRunQ().single());
static void thread_yield_fast() {
auto sw = AtomicRunQ().goto_next();
switch_context(sw.from, sw.to);
}

void thread_yield_to(thread* th) {
int thread_yield_to(thread* th) {
if (unlikely(th == nullptr)) { // yield to any thread
return thread_yield();
}
RunQ rq;
if (unlikely(th == rq.current)) { // yield to current should just update time
if_update_now();
return;
return 0;
} else if (unlikely(th->vcpu != rq.current->vcpu)) {
LOG_ERROR_RETURN(EINVAL, , "target thread ` must be run by the same vcpu as CURRENT!", th);
LOG_ERROR_RETURN(EINVAL, -1, "target thread ` must be run by the same vcpu as CURRENT!", th);
} else if (unlikely(th->state == states::STANDBY)) {
while (th->state == states::STANDBY)
resume_threads();
assert(th->state == states::READY);
} else if (unlikely(th->state != states::READY)) {
LOG_ERROR_RETURN(EINVAL, , "target thread ` must be READY!", th);
LOG_ERROR_RETURN(EINVAL, -1, "target thread ` must be READY!", th);
}

auto sw = AtomicRunQ(rq).try_goto(th);
if_update_now();
rq.current->error_number = 0;
switch_context(sw.from, sw.to);
return rq.current->error_number;
}

__attribute__((always_inline)) inline
Expand All @@ -1220,13 +1223,16 @@ R"(
sw.from->get_vcpu()->sleepq.push(sw.from);
return sw;
}

inline int yield_as_sleep() {
int ret = thread_yield();
if (unlikely(ret)) { errno = ret; return -1; }
return 0;
}
// returns 0 if slept well (at lease `useconds`), -1 otherwise
static int thread_usleep(uint64_t useconds, thread_list* waitq)
{
if (unlikely(useconds == 0)) {
thread_yield();
return 0;
return yield_as_sleep();
}

auto r = prepare_usleep(useconds, waitq);
Expand Down Expand Up @@ -1298,7 +1304,7 @@ R"(
if (unlikely(!rq.current))
LOG_ERROR_RETURN(ENOSYS, -1, "Photon not initialized in this thread");
if (unlikely(!useconds))
return thread_yield(), 0;
return yield_as_sleep();
if (unlikely(rq.current->is_shutting_down()))
return do_shutdown_usleep(useconds, rq);
return do_thread_usleep(useconds, rq);
Expand All @@ -1325,9 +1331,14 @@ R"(
{
if (unlikely(!th))
LOG_ERROR_RETURN(EINVAL, , "invalid parameter");
if (unlikely(th->state != states::SLEEPING)) return;
if (unlikely(th->state != states::SLEEPING)) {
out: // may have thread_yield()-ed
if (th->state != states::READY || th->error_number == 0)
th->error_number = error_number;
return;
}
SCOPED_LOCK(th->lock);
if (unlikely(th->state != states::SLEEPING)) return;
if (unlikely(th->state != states::SLEEPING)) goto out;

prelocked_thread_interrupt(th, error_number);
}
Expand Down Expand Up @@ -1558,7 +1569,11 @@ R"(
for (int tries = 0; tries < MaxTries; ++tries) {
if (try_lock() == 0)
return 0;
thread_yield();
int ret = thread_yield();
if (unlikely(ret)) {
errno = ret;
return -1;
}
}
splock.lock();
if (try_lock() == 0) {
Expand Down
6 changes: 4 additions & 2 deletions thread/thread.h
Original file line number Diff line number Diff line change
Expand Up @@ -68,10 +68,12 @@ namespace photon
void thread_join(join_handle* jh);

// switching to other threads (without going into sleep queue)
void thread_yield();
// return error_number if interrupted during the rolling
int thread_yield();

// switching to a specific thread, which must be RUNNING
void thread_yield_to(thread* th);
// return error_number if interrupted during the rolling
int thread_yield_to(thread* th);

// suspend CURRENT thread for specified time duration, and switch
// control to other threads, resuming possible sleepers.
Expand Down

0 comments on commit 6f577f3

Please sign in to comment.