uti: Call into McKernel futex()
(1) Masquerade clv
(2) Fix timeout
(3) Let mcexec thread with the same tid as McKernel thread migrating
to Linux handles the migration request
(4) Call create_tracer() before creating proxy related objects
Change-Id: I6b2689b70db49827f10aa7d5a4c581aa81319b55
This commit is contained in:
@@ -283,6 +283,8 @@ struct mcos_handler_info {
|
||||
int cpu;
|
||||
struct mcctrl_usrdata *ud;
|
||||
struct file *file;
|
||||
unsigned long user_start;
|
||||
unsigned long user_end;
|
||||
};
|
||||
|
||||
struct mcos_handler_info;
|
||||
@@ -420,6 +422,8 @@ static long mcexec_start_image(ihk_os_t os,
|
||||
|
||||
info->pid = desc->pid;
|
||||
info->cpu = desc->cpu;
|
||||
info->user_start = desc->user_start;
|
||||
info->user_end = desc->user_end;
|
||||
ihk_os_register_release_handler(file, release_handler, info);
|
||||
ihk_os_set_mcos_private_data(file, info);
|
||||
|
||||
@@ -1198,9 +1202,28 @@ int mcexec_syscall(struct mcctrl_usrdata *ud, struct ikc_scd_packet *packet)
|
||||
wqhln = wqhln_iter;
|
||||
break;
|
||||
}
|
||||
if (!wqhln) {
|
||||
printk("%s: WARNING: no target thread found for exact request??\n",
|
||||
__FUNCTION__);
|
||||
/* Find the mcexec thread with the same tid as the requesting McKernel thread
|
||||
and let it handle the migrate-to-Linux request */
|
||||
if (packet->req.number == __NR_sched_setaffinity && packet->req.args[0] == 0) {
|
||||
list_for_each_entry(wqhln_iter, &ppd->wq_list, list) {
|
||||
if (packet->req.ttid == wqhln_iter->rtid) {
|
||||
if (!wqhln_iter->task) {
|
||||
printk("%s: ERROR: wqhln_iter->task=%p,rtid=%d,&ppd->wq_list_lock=%p\n", __FUNCTION__, wqhln_iter->task, wqhln_iter->rtid, &ppd->wq_list_lock);
|
||||
} else if(wqhln_iter->req) {
|
||||
/* list_del() is called after woken-up */
|
||||
dprintk("%s: INFO: target thread is busy, wqhln_iter->req=%d,rtid=%d,&ppd->wq_list_lock=%p\n", __FUNCTION__, wqhln_iter->req, wqhln_iter->rtid, &ppd->wq_list_lock);
|
||||
} else {
|
||||
wqhln = wqhln_iter;
|
||||
dprintk("%s: uti, worker with tid of %d found in wq_list\n", __FUNCTION__, packet->req.ttid);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (!wqhln) {
|
||||
printk("%s: WARNING: no target thread (tid=%d) found for exact request??\n",
|
||||
__FUNCTION__, packet->req.ttid);
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Is there any thread available? */
|
||||
@@ -1225,6 +1248,12 @@ retry_alloc:
|
||||
wqhln = wqhln_alloc;
|
||||
wqhln->req = 0;
|
||||
wqhln->task = NULL;
|
||||
/* Let the mcexec thread to handle migrate-to-Linux request in mcexec_wait_syscall() after finishing the current task */
|
||||
if (packet->req.number == __NR_sched_setaffinity && packet->req.args[0] == 0) {
|
||||
wqhln->rtid = packet->req.ttid;
|
||||
} else {
|
||||
wqhln->rtid = 0;
|
||||
}
|
||||
init_waitqueue_head(&wqhln->wq_syscall);
|
||||
list_add_tail(&wqhln->list, &ppd->wq_req_list);
|
||||
}
|
||||
@@ -1272,16 +1301,27 @@ int mcexec_wait_syscall(ihk_os_t os, struct syscall_wait_desc *__user req)
|
||||
retry:
|
||||
/* Prepare per-thread wait queue head or find a valid request */
|
||||
irqflags = ihk_ikc_spinlock_lock(&ppd->wq_list_lock);
|
||||
|
||||
/* Handle migrate-to-Linux request if any */
|
||||
list_for_each_entry(wqhln_iter, &ppd->wq_req_list, list) {
|
||||
if (wqhln_iter->rtid == task_pid_vnr(current)) {
|
||||
wqhln = wqhln_iter;
|
||||
wqhln->task = current;
|
||||
list_del(&wqhln->list);
|
||||
goto found;
|
||||
}
|
||||
}
|
||||
|
||||
/* First see if there is a valid request already that is not yet taken */
|
||||
list_for_each_entry(wqhln_iter, &ppd->wq_req_list, list) {
|
||||
if (wqhln_iter->task == NULL && wqhln_iter->req) {
|
||||
if (!wqhln_iter->rtid && wqhln_iter->task == NULL && wqhln_iter->req) {
|
||||
wqhln = wqhln_iter;
|
||||
wqhln->task = current;
|
||||
list_del(&wqhln->list);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
found:
|
||||
if (!wqhln) {
|
||||
retry_alloc:
|
||||
wqhln = kmalloc(sizeof(*wqhln), GFP_ATOMIC);
|
||||
@@ -1293,6 +1333,8 @@ retry_alloc:
|
||||
wqhln->task = current;
|
||||
wqhln->req = 0;
|
||||
wqhln->packet = NULL;
|
||||
/* Let mcexec_syscall() find the mcexec thread to handle migrate-to-Linux request */
|
||||
wqhln->rtid = task_pid_vnr(current);
|
||||
init_waitqueue_head(&wqhln->wq_syscall);
|
||||
|
||||
list_add(&wqhln->list, &ppd->wq_list);
|
||||
@@ -2354,6 +2396,8 @@ mcexec_util_thread2(ihk_os_t os, unsigned long arg, struct file *file)
|
||||
void **__user param = (void **__user )arg;
|
||||
void *__user rctx = (void *__user)param[1];
|
||||
void *__user lctx = (void *__user)param[2];
|
||||
struct mcctrl_usrdata *usrdata = ihk_host_os_get_usrdata(os);
|
||||
struct mcctrl_per_proc_data *ppd;
|
||||
|
||||
save_fs_ctx(lctx);
|
||||
info = ihk_os_get_mcos_private_data(file);
|
||||
@@ -2451,34 +2495,148 @@ err:
|
||||
kfree(thread);
|
||||
return 0;
|
||||
}
|
||||
|
||||
long mcexec_unmap_pseudo_filemap(ihk_os_t os, struct file *file)
|
||||
{
|
||||
long rc = -1;
|
||||
struct mcos_handler_info *info;
|
||||
info = ihk_os_get_mcos_private_data(file);
|
||||
dprintk("%s: clear_pte_range %p-%p\n", __FUNCTION__, (void*)info->user_start, (void*)info->user_end);
|
||||
rc = clear_pte_range(info->user_start, info->user_end - info->user_start);
|
||||
return rc;
|
||||
}
|
||||
|
||||
long
|
||||
mcexec_syscall_thread(ihk_os_t os, unsigned long arg, struct file *file)
|
||||
static long (*mckernel_do_futex)(int n, unsigned long arg0, unsigned long arg1,
|
||||
unsigned long arg2, unsigned long arg3,
|
||||
unsigned long arg4, unsigned long arg5,
|
||||
unsigned long _uti_clv,
|
||||
void *uti_futex_resp,
|
||||
void *_linux_wait_event,
|
||||
void *_linux_printk,
|
||||
void *_linux_clock_gettime);
|
||||
|
||||
long uti_wait_event(void *_resp, unsigned long nsec_timeout) {
|
||||
struct uti_futex_resp *resp = _resp;
|
||||
if (nsec_timeout) {
|
||||
return wait_event_interruptible_timeout(resp->wq, resp->done, nsecs_to_jiffies(nsec_timeout));
|
||||
} else {
|
||||
return wait_event_interruptible(resp->wq, resp->done);
|
||||
}
|
||||
}
|
||||
|
||||
int uti_printk(const char *fmt, ...) {
|
||||
int sum = 0, nwritten;
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
nwritten = vprintk(fmt, args);
|
||||
sum += nwritten;
|
||||
va_end(args);
|
||||
return sum;
|
||||
}
|
||||
|
||||
int uti_clock_gettime(clockid_t clk_id, struct timespec *tp) {
|
||||
int ret = 0;
|
||||
struct timespec64 ts64;
|
||||
dprintk("%s: clk_id=%x,REALTIME=%x,MONOTONIC=%x\n", __FUNCTION__, clk_id, CLOCK_REALTIME, CLOCK_MONOTONIC);
|
||||
switch(clk_id) {
|
||||
case CLOCK_REALTIME:
|
||||
getnstimeofday64(&ts64);
|
||||
tp->tv_sec = ts64.tv_sec;
|
||||
tp->tv_nsec = ts64.tv_nsec;
|
||||
dprintk("%s: CLOCK_REALTIME,%ld.%09ld\n", __FUNCTION__, tp->tv_sec, tp->tv_nsec);
|
||||
break;
|
||||
case CLOCK_MONOTONIC: {
|
||||
/* Do not use getrawmonotonic() because it returns different value than clock_gettime() */
|
||||
ktime_get_ts64(&ts64);
|
||||
tp->tv_sec = ts64.tv_sec;
|
||||
tp->tv_nsec = ts64.tv_nsec;
|
||||
dprintk("%s: CLOCK_MONOTONIC,%ld.%09ld\n", __FUNCTION__, tp->tv_sec, tp->tv_nsec);
|
||||
break; }
|
||||
default:
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
long mcexec_syscall_thread(ihk_os_t os, unsigned long arg, struct file *file)
|
||||
{
|
||||
struct syscall_struct {
|
||||
int number;
|
||||
unsigned long args[6];
|
||||
unsigned long ret;
|
||||
unsigned long uti_clv; /* copy of a clv in McKernel */
|
||||
};
|
||||
struct syscall_struct param;
|
||||
struct syscall_struct __user *uparam =
|
||||
(struct syscall_struct __user *)arg;
|
||||
int rc;
|
||||
long rc;
|
||||
|
||||
if (copy_from_user(¶m, uparam, sizeof param)) {
|
||||
return -EFAULT;
|
||||
}
|
||||
rc = syscall_backward(ihk_host_os_get_usrdata(os), param.number,
|
||||
param.args[0], param.args[1], param.args[2],
|
||||
param.args[3], param.args[4], param.args[5],
|
||||
¶m.ret);
|
||||
#if 1 /* debug */
|
||||
if (param.number == __NR_futex) {
|
||||
#else
|
||||
if (0) {
|
||||
#endif
|
||||
struct uti_futex_resp resp = {
|
||||
.done = 0
|
||||
};
|
||||
init_waitqueue_head(&resp.wq);
|
||||
|
||||
if (!mckernel_do_futex) {
|
||||
if (ihk_os_get_special_address(os, IHK_SPADDR_MCKERNEL_DO_FUTEX,
|
||||
(unsigned long *)&mckernel_do_futex,
|
||||
NULL)) {
|
||||
kprintf("%s: ihk_os_get_special_address failed\n", __FUNCTION__);
|
||||
return -EINVAL;
|
||||
}
|
||||
dprintk("%s: mckernel_do_futex=%p\n", __FUNCTION__, mckernel_do_futex);
|
||||
}
|
||||
|
||||
rc = (*mckernel_do_futex)(param.number, param.args[0], param.args[1], param.args[2],
|
||||
param.args[3], param.args[4], param.args[5], param.uti_clv, (void *)&resp, (void *)uti_wait_event, (void *)uti_printk, (void *)uti_clock_gettime);
|
||||
param.ret = rc;
|
||||
} else {
|
||||
dprintk("%s: syscall_backward, SC %d, tid %d\n", __FUNCTION__, param.number, task_tgid_vnr(current));
|
||||
rc = syscall_backward(ihk_host_os_get_usrdata(os), param.number,
|
||||
param.args[0], param.args[1], param.args[2],
|
||||
param.args[3], param.args[4], param.args[5],
|
||||
¶m.ret);
|
||||
}
|
||||
if (copy_to_user(&uparam->ret, ¶m.ret, sizeof(unsigned long))) {
|
||||
return -EFAULT;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
void mcctrl_futex_wake(struct ikc_scd_packet *pisp)
|
||||
{
|
||||
struct uti_futex_resp *resp;
|
||||
|
||||
/* Guard the access to pisp->futex.resp, which is dead out of mcexec_syscall_thread() */
|
||||
if (*pisp->futex.spin_sleep == 0) {
|
||||
dprintk("%s: DEBUG: woken up by someone else\n", __FUNCTION__);
|
||||
return;
|
||||
}
|
||||
|
||||
resp = pisp->futex.resp;
|
||||
if (!resp) {
|
||||
kprintf("%s: ERROR: pisp->futex.resp is NULL\n", __FUNCTION__);
|
||||
return;
|
||||
}
|
||||
|
||||
if (*pisp->futex.spin_sleep == 0) {
|
||||
kprintf("%s: ERROR: resp is dead\n", __FUNCTION__);
|
||||
return;
|
||||
}
|
||||
|
||||
resp->done = 1;
|
||||
wake_up_interruptible(&resp->wq);
|
||||
}
|
||||
|
||||
|
||||
static struct ihk_cache_topology *
|
||||
cache_topo_search(struct ihk_cpu_topology *cpu_topo, int level)
|
||||
{
|
||||
@@ -2838,6 +2996,9 @@ long __mcctrl_control(ihk_os_t os, unsigned int req, unsigned long arg,
|
||||
case MCEXEC_UP_TERMINATE_THREAD:
|
||||
return mcexec_terminate_thread(os, (unsigned long *)arg, file);
|
||||
|
||||
case MCEXEC_UP_UNMAP_PSEUDO_FILEMAP:
|
||||
return mcexec_unmap_pseudo_filemap(os, file);
|
||||
|
||||
case MCEXEC_UP_GET_NUM_POOL_THREADS:
|
||||
return mcctrl_get_num_pool_threads(os);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user