Fix sched agent failure for offline core
This commit is contained in:
parent
7a87d77509
commit
25350b0e85
@ -72,6 +72,10 @@ enclave {
|
|||||||
size_t cpusize,
|
size_t cpusize,
|
||||||
[in, size=cpusize] const unsigned char* buf
|
[in, size=cpusize] const unsigned char* buf
|
||||||
) propagate_errno;
|
) propagate_errno;
|
||||||
|
int occlum_ocall_sched_getaffinity(
|
||||||
|
size_t cpusize,
|
||||||
|
[out, size=cpusize] unsigned char* buf
|
||||||
|
) propagate_errno;
|
||||||
int occlum_ocall_ncores(void);
|
int occlum_ocall_ncores(void);
|
||||||
|
|
||||||
sgx_status_t occlum_ocall_sgx_init_quote(
|
sgx_status_t occlum_ocall_sgx_init_quote(
|
||||||
|
@ -52,6 +52,11 @@ impl CpuSet {
|
|||||||
self.bits.count_ones() == 0
|
self.bits.count_ones() == 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Returns if the CpuSet is a subset of available cpu set
|
||||||
|
pub fn is_subset_of(&self, other: &CpuSet) -> bool {
|
||||||
|
(self.bits.clone() & other.bits.clone()) == self.bits
|
||||||
|
}
|
||||||
|
|
||||||
/// Create a CpuSet from bits given in a byte slice.
|
/// Create a CpuSet from bits given in a byte slice.
|
||||||
pub fn from_slice(slice: &[u8]) -> Result<Self> {
|
pub fn from_slice(slice: &[u8]) -> Result<Self> {
|
||||||
if slice.len() < Self::len() {
|
if slice.len() < Self::len() {
|
||||||
@ -71,6 +76,10 @@ impl CpuSet {
|
|||||||
self.bits.as_slice()
|
self.bits.as_slice()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn as_mut_slice(&mut self) -> &mut [u8] {
|
||||||
|
self.bits.as_mut_slice()
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns an iterator that allows accessing the underlying bits.
|
/// Returns an iterator that allows accessing the underlying bits.
|
||||||
pub fn iter(&self) -> Iter {
|
pub fn iter(&self) -> Iter {
|
||||||
self.bits.iter()
|
self.bits.iter()
|
||||||
@ -120,4 +129,29 @@ lazy_static! {
|
|||||||
ncores as usize
|
ncores as usize
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// The set of all available CPU cores.
|
||||||
|
///
|
||||||
|
/// While `AVAIL_CPUSET` is likely to be equal to `CpuSet::new_full()`, this is not always the
|
||||||
|
/// case. For example, when the enclave is running on a container or a virtual machine on a public
|
||||||
|
/// cloud platform, the container or vm is usually given access to a subset of the CPU cores on
|
||||||
|
/// the host machine.
|
||||||
|
///
|
||||||
|
/// Property: `AVAIL_CPU.empty() == false`.
|
||||||
|
pub static ref AVAIL_CPUSET: CpuSet = {
|
||||||
|
extern "C" {
|
||||||
|
fn occlum_ocall_sched_getaffinity(
|
||||||
|
ret: *mut i32,
|
||||||
|
cpusetsize: size_t,
|
||||||
|
mask: *mut c_uchar,
|
||||||
|
) -> sgx_status_t;
|
||||||
|
}
|
||||||
|
let mut cpuset = CpuSet::new_empty();
|
||||||
|
let mut retval = 0;
|
||||||
|
let sgx_status = unsafe{occlum_ocall_sched_getaffinity(&mut retval, CpuSet::len(), cpuset.as_mut_slice().as_mut_ptr())};
|
||||||
|
assert!(sgx_status == sgx_status_t::SGX_SUCCESS);
|
||||||
|
CpuSet::clear_unused(&mut cpuset.bits);
|
||||||
|
assert!(!cpuset.empty());
|
||||||
|
cpuset
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
@ -21,7 +21,7 @@
|
|||||||
//! immediately to the host OS thread---until SchedAgent is detached from the
|
//! immediately to the host OS thread---until SchedAgent is detached from the
|
||||||
//! host OS thread.
|
//! host OS thread.
|
||||||
|
|
||||||
use super::cpu_set::CpuSet;
|
use super::cpu_set::{CpuSet, AVAIL_CPUSET};
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use crate::util::dirty::Dirty;
|
use crate::util::dirty::Dirty;
|
||||||
|
|
||||||
@ -42,7 +42,7 @@ enum Inner {
|
|||||||
impl SchedAgent {
|
impl SchedAgent {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
let inner = Some({
|
let inner = Some({
|
||||||
let affinity = Dirty::new(CpuSet::new_full());
|
let affinity = Dirty::new(AVAIL_CPUSET.clone());
|
||||||
Inner::Detached { affinity }
|
Inner::Detached { affinity }
|
||||||
});
|
});
|
||||||
Self { inner }
|
Self { inner }
|
||||||
@ -59,6 +59,12 @@ impl SchedAgent {
|
|||||||
if new_affinity.empty() {
|
if new_affinity.empty() {
|
||||||
return_errno!(EINVAL, "there must be at least one CPU core in the CpuSet");
|
return_errno!(EINVAL, "there must be at least one CPU core in the CpuSet");
|
||||||
}
|
}
|
||||||
|
if !new_affinity.is_subset_of(&AVAIL_CPUSET) {
|
||||||
|
return_errno!(
|
||||||
|
EINVAL,
|
||||||
|
"one or some of the CPU cores are not available to set"
|
||||||
|
);
|
||||||
|
}
|
||||||
match self.inner_mut() {
|
match self.inner_mut() {
|
||||||
Inner::Detached { affinity } => {
|
Inner::Detached { affinity } => {
|
||||||
*affinity.as_mut() = new_affinity;
|
*affinity.as_mut() = new_affinity;
|
||||||
|
@ -3,6 +3,16 @@
|
|||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include "ocalls.h"
|
#include "ocalls.h"
|
||||||
|
|
||||||
|
int occlum_ocall_sched_getaffinity(size_t cpusize, unsigned char* buf) {
|
||||||
|
int ret;
|
||||||
|
cpu_set_t mask;
|
||||||
|
CPU_ZERO(&mask);
|
||||||
|
|
||||||
|
ret = syscall(__NR_sched_getaffinity, gettid(), sizeof(cpu_set_t), &mask);
|
||||||
|
memcpy(buf, &mask, cpusize);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
int occlum_ocall_sched_setaffinity(int host_tid, size_t cpusize, const unsigned char* buf) {
|
int occlum_ocall_sched_setaffinity(int host_tid, size_t cpusize, const unsigned char* buf) {
|
||||||
return syscall(__NR_sched_setaffinity, host_tid, cpusize, buf);
|
return syscall(__NR_sched_setaffinity, host_tid, cpusize, buf);
|
||||||
}
|
}
|
||||||
|
@ -11,6 +11,37 @@
|
|||||||
#include <sys/wait.h>
|
#include <sys/wait.h>
|
||||||
#include "test.h"
|
#include "test.h"
|
||||||
|
|
||||||
|
// ============================================================================
|
||||||
|
// Helper function
|
||||||
|
// ============================================================================
|
||||||
|
|
||||||
|
#define MAX_CPU_NUM 1024
|
||||||
|
|
||||||
|
static int* g_online_cpu_idxs;
|
||||||
|
|
||||||
|
int get_online_cpu() {
|
||||||
|
int online_num = sysconf(_SC_NPROCESSORS_ONLN);
|
||||||
|
cpu_set_t mask;
|
||||||
|
int index = 0;
|
||||||
|
|
||||||
|
g_online_cpu_idxs = (int*)calloc(online_num, sizeof(int));
|
||||||
|
CPU_ZERO(&mask);
|
||||||
|
if (sched_getaffinity(0, sizeof(cpu_set_t), &mask) < 0) {
|
||||||
|
THROW_ERROR("failed to call sched_getaffinity");
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("Online Core No: ");
|
||||||
|
for (int i = 0; index < online_num && i < MAX_CPU_NUM; i++) {
|
||||||
|
if (CPU_ISSET(i, &mask)) {
|
||||||
|
g_online_cpu_idxs[index] = i;
|
||||||
|
index++;
|
||||||
|
printf("%d ", i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
// Test cases for sched_cpu_affinity
|
// Test cases for sched_cpu_affinity
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
@ -32,12 +63,13 @@ static int test_sched_getaffinity_with_self_pid() {
|
|||||||
static int test_sched_setaffinity_with_self_pid() {
|
static int test_sched_setaffinity_with_self_pid() {
|
||||||
int nproc = sysconf(_SC_NPROCESSORS_ONLN);
|
int nproc = sysconf(_SC_NPROCESSORS_ONLN);
|
||||||
cpu_set_t mask_old;
|
cpu_set_t mask_old;
|
||||||
|
CPU_ZERO(&mask_old);
|
||||||
for (int i = 0; i < nproc; ++i) {
|
for (int i = 0; i < nproc; ++i) {
|
||||||
CPU_SET(i, &mask_old);
|
CPU_SET(g_online_cpu_idxs[i], &mask_old);
|
||||||
}
|
}
|
||||||
cpu_set_t mask;
|
cpu_set_t mask;
|
||||||
CPU_ZERO(&mask);
|
CPU_ZERO(&mask);
|
||||||
CPU_SET(0, &mask);
|
CPU_SET(g_online_cpu_idxs[0], &mask);
|
||||||
if (sched_setaffinity(0, sizeof(cpu_set_t), &mask) < 0) {
|
if (sched_setaffinity(0, sizeof(cpu_set_t), &mask) < 0) {
|
||||||
THROW_ERROR("failed to call sched_setaffinity \n");
|
THROW_ERROR("failed to call sched_setaffinity \n");
|
||||||
}
|
}
|
||||||
@ -56,13 +88,13 @@ static int test_sched_setaffinity_with_self_pid() {
|
|||||||
|
|
||||||
static int test_sched_xetaffinity_with_child_pid() {
|
static int test_sched_xetaffinity_with_child_pid() {
|
||||||
int status, child_pid;
|
int status, child_pid;
|
||||||
int num = sysconf(_SC_NPROCESSORS_CONF);
|
int num = sysconf(_SC_NPROCESSORS_ONLN);
|
||||||
if (num <= 0) {
|
if (num <= 0) {
|
||||||
THROW_ERROR("failed to get cpu number");
|
THROW_ERROR("failed to get cpu number");
|
||||||
}
|
}
|
||||||
cpu_set_t mask;
|
cpu_set_t mask;
|
||||||
CPU_ZERO(&mask);
|
CPU_ZERO(&mask);
|
||||||
CPU_SET(num - 1 , &mask);
|
CPU_SET(g_online_cpu_idxs[num - 1] , &mask);
|
||||||
int ret = posix_spawn(&child_pid, "/bin/getpid", NULL, NULL, NULL, NULL);
|
int ret = posix_spawn(&child_pid, "/bin/getpid", NULL, NULL, NULL, NULL);
|
||||||
if (ret < 0 ) {
|
if (ret < 0 ) {
|
||||||
THROW_ERROR("spawn process error");
|
THROW_ERROR("spawn process error");
|
||||||
@ -99,7 +131,7 @@ static int test_sched_getaffinity_via_explicit_syscall() {
|
|||||||
static int test_sched_setaffinity_via_explicit_syscall() {
|
static int test_sched_setaffinity_via_explicit_syscall() {
|
||||||
cpu_set_t mask;
|
cpu_set_t mask;
|
||||||
CPU_ZERO(&mask);
|
CPU_ZERO(&mask);
|
||||||
CPU_SET(0, &mask);
|
CPU_SET(g_online_cpu_idxs[0], &mask);
|
||||||
if (syscall(__NR_sched_setaffinity, 0, sizeof(cpu_set_t), &mask) < 0) {
|
if (syscall(__NR_sched_setaffinity, 0, sizeof(cpu_set_t), &mask) < 0) {
|
||||||
THROW_ERROR("failed to call __NR_sched_setaffinity");
|
THROW_ERROR("failed to call __NR_sched_setaffinity");
|
||||||
}
|
}
|
||||||
@ -117,8 +149,9 @@ static int test_sched_setaffinity_via_explicit_syscall() {
|
|||||||
// Recover the affinity mask
|
// Recover the affinity mask
|
||||||
int nproc = sysconf(_SC_NPROCESSORS_ONLN);
|
int nproc = sysconf(_SC_NPROCESSORS_ONLN);
|
||||||
cpu_set_t mask_old;
|
cpu_set_t mask_old;
|
||||||
|
CPU_ZERO(&mask_old);
|
||||||
for (int i = 0; i < nproc; ++i) {
|
for (int i = 0; i < nproc; ++i) {
|
||||||
CPU_SET(i, &mask_old);
|
CPU_SET(g_online_cpu_idxs[i], &mask_old);
|
||||||
}
|
}
|
||||||
if (syscall(__NR_sched_setaffinity, 0, sizeof(cpu_set_t), &mask_old) < 0) {
|
if (syscall(__NR_sched_setaffinity, 0, sizeof(cpu_set_t), &mask_old) < 0) {
|
||||||
THROW_ERROR("recover cpuset error");
|
THROW_ERROR("recover cpuset error");
|
||||||
@ -188,5 +221,9 @@ static test_case_t test_cases[] = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
return test_suite_run(test_cases, ARRAY_SIZE(test_cases));
|
int ret;
|
||||||
|
get_online_cpu();
|
||||||
|
ret = test_suite_run(test_cases, ARRAY_SIZE(test_cases));
|
||||||
|
free(g_online_cpu_idxs);
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user