forked from M-Labs/artiq
Add zero-cost exception support to runtime and host.
This commit is contained in:
parent
1d61e446cb
commit
27d2390fed
@ -86,6 +86,7 @@ class TException(types.TMono):
|
|||||||
("__file__", TStr()),
|
("__file__", TStr()),
|
||||||
("__line__", TInt(types.TValue(32))),
|
("__line__", TInt(types.TValue(32))),
|
||||||
("__col__", TInt(types.TValue(32))),
|
("__col__", TInt(types.TValue(32))),
|
||||||
|
("__func__", TStr()),
|
||||||
("__message__", TStr()),
|
("__message__", TStr()),
|
||||||
("__param0__", TInt(types.TValue(64))),
|
("__param0__", TInt(types.TValue(64))),
|
||||||
("__param1__", TInt(types.TValue(64))),
|
("__param1__", TInt(types.TValue(64))),
|
||||||
|
@ -157,7 +157,7 @@ class ARTIQIRGenerator(algorithm.Visitor):
|
|||||||
|
|
||||||
def visit_function(self, node, is_lambda, is_internal):
|
def visit_function(self, node, is_lambda, is_internal):
|
||||||
if is_lambda:
|
if is_lambda:
|
||||||
name = "lambda.{}.{}".format(node.loc.line(), node.loc.column())
|
name = "lambda@{}:{}".format(node.loc.line(), node.loc.column())
|
||||||
typ = node.type.find()
|
typ = node.type.find()
|
||||||
else:
|
else:
|
||||||
name = node.name
|
name = node.name
|
||||||
@ -471,9 +471,11 @@ class ARTIQIRGenerator(algorithm.Visitor):
|
|||||||
loc_file = ir.Constant(self.current_loc.source_buffer.name, builtins.TStr())
|
loc_file = ir.Constant(self.current_loc.source_buffer.name, builtins.TStr())
|
||||||
loc_line = ir.Constant(self.current_loc.line(), builtins.TInt(types.TValue(32)))
|
loc_line = ir.Constant(self.current_loc.line(), builtins.TInt(types.TValue(32)))
|
||||||
loc_column = ir.Constant(self.current_loc.column(), builtins.TInt(types.TValue(32)))
|
loc_column = ir.Constant(self.current_loc.column(), builtins.TInt(types.TValue(32)))
|
||||||
|
loc_function = ir.Constant(".".join(self.name), builtins.TStr())
|
||||||
self.append(ir.SetAttr(exn, "__file__", loc_file))
|
self.append(ir.SetAttr(exn, "__file__", loc_file))
|
||||||
self.append(ir.SetAttr(exn, "__line__", loc_line))
|
self.append(ir.SetAttr(exn, "__line__", loc_line))
|
||||||
self.append(ir.SetAttr(exn, "__col__", loc_column))
|
self.append(ir.SetAttr(exn, "__col__", loc_column))
|
||||||
|
self.append(ir.SetAttr(exn, "__func__", loc_function))
|
||||||
|
|
||||||
if self.unwind_target is not None:
|
if self.unwind_target is not None:
|
||||||
self.append(ir.Raise(exn, self.unwind_target))
|
self.append(ir.Raise(exn, self.unwind_target))
|
||||||
@ -1237,6 +1239,7 @@ class ARTIQIRGenerator(algorithm.Visitor):
|
|||||||
ir.Constant("<not thrown>", builtins.TStr()), # file
|
ir.Constant("<not thrown>", builtins.TStr()), # file
|
||||||
ir.Constant(0, builtins.TInt(types.TValue(32))), # line
|
ir.Constant(0, builtins.TInt(types.TValue(32))), # line
|
||||||
ir.Constant(0, builtins.TInt(types.TValue(32))), # column
|
ir.Constant(0, builtins.TInt(types.TValue(32))), # column
|
||||||
|
ir.Constant("<not thrown>", builtins.TStr()), # function
|
||||||
]
|
]
|
||||||
|
|
||||||
if message is None:
|
if message is None:
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import struct
|
import struct
|
||||||
import logging
|
import logging
|
||||||
|
import traceback
|
||||||
from enum import Enum
|
from enum import Enum
|
||||||
from fractions import Fraction
|
from fractions import Fraction
|
||||||
|
|
||||||
@ -18,11 +19,12 @@ class _H2DMsgType(Enum):
|
|||||||
RUN_KERNEL = 5
|
RUN_KERNEL = 5
|
||||||
|
|
||||||
RPC_REPLY = 6
|
RPC_REPLY = 6
|
||||||
|
RPC_EXCEPTION = 7
|
||||||
|
|
||||||
FLASH_READ_REQUEST = 7
|
FLASH_READ_REQUEST = 8
|
||||||
FLASH_WRITE_REQUEST = 8
|
FLASH_WRITE_REQUEST = 9
|
||||||
FLASH_ERASE_REQUEST = 9
|
FLASH_ERASE_REQUEST = 10
|
||||||
FLASH_REMOVE_REQUEST = 10
|
FLASH_REMOVE_REQUEST = 11
|
||||||
|
|
||||||
|
|
||||||
class _D2HMsgType(Enum):
|
class _D2HMsgType(Enum):
|
||||||
@ -223,16 +225,12 @@ class CommGeneric:
|
|||||||
|
|
||||||
self._read_empty(_D2HMsgType.CLOCK_SWITCH_COMPLETED)
|
self._read_empty(_D2HMsgType.CLOCK_SWITCH_COMPLETED)
|
||||||
|
|
||||||
def load(self, kernel_library):
|
def get_log(self):
|
||||||
self._write_header(_H2DMsgType.LOAD_LIBRARY)
|
self._write_empty(_H2DMsgType.LOG_REQUEST)
|
||||||
self._write_chunk(kernel_library)
|
|
||||||
self._write_flush()
|
|
||||||
|
|
||||||
self._read_empty(_D2HMsgType.LOAD_COMPLETED)
|
self._read_header()
|
||||||
|
self._read_expect(_D2HMsgType.LOG_REPLY)
|
||||||
def run(self):
|
return self._read_chunk(self._read_length).decode('utf-8')
|
||||||
self._write_empty(_H2DMsgType.RUN_KERNEL)
|
|
||||||
logger.debug("running kernel")
|
|
||||||
|
|
||||||
def flash_storage_read(self, key):
|
def flash_storage_read(self, key):
|
||||||
self._write_header(_H2DMsgType.FLASH_READ_REQUEST)
|
self._write_header(_H2DMsgType.FLASH_READ_REQUEST)
|
||||||
@ -267,7 +265,18 @@ class CommGeneric:
|
|||||||
|
|
||||||
self._read_empty(_D2HMsgType.FLASH_OK_REPLY)
|
self._read_empty(_D2HMsgType.FLASH_OK_REPLY)
|
||||||
|
|
||||||
def _receive_rpc_value(self, tag):
|
def load(self, kernel_library):
|
||||||
|
self._write_header(_H2DMsgType.LOAD_LIBRARY)
|
||||||
|
self._write_chunk(kernel_library)
|
||||||
|
self._write_flush()
|
||||||
|
|
||||||
|
self._read_empty(_D2HMsgType.LOAD_COMPLETED)
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
self._write_empty(_H2DMsgType.RUN_KERNEL)
|
||||||
|
logger.debug("running kernel")
|
||||||
|
|
||||||
|
def _receive_rpc_value(self, tag, rpc_map):
|
||||||
if tag == "n":
|
if tag == "n":
|
||||||
return None
|
return None
|
||||||
elif tag == "b":
|
elif tag == "b":
|
||||||
@ -286,37 +295,83 @@ class CommGeneric:
|
|||||||
elt_tag = chr(self._read_int8())
|
elt_tag = chr(self._read_int8())
|
||||||
length = self._read_int32()
|
length = self._read_int32()
|
||||||
return [self._receive_rpc_value(elt_tag) for _ in range(length)]
|
return [self._receive_rpc_value(elt_tag) for _ in range(length)]
|
||||||
|
elif tag == "o":
|
||||||
|
return rpc_map[self._read_int32()]
|
||||||
else:
|
else:
|
||||||
raise IOError("Unknown RPC value tag: {}", tag)
|
raise IOError("Unknown RPC value tag: {}", tag)
|
||||||
|
|
||||||
def _receive_rpc_values(self):
|
def _receive_rpc_values(self, rpc_map):
|
||||||
result = []
|
result = []
|
||||||
while True:
|
while True:
|
||||||
tag = chr(self._read_int8())
|
tag = chr(self._read_int8())
|
||||||
if tag == "\x00":
|
if tag == "\x00":
|
||||||
return result
|
return result
|
||||||
else:
|
else:
|
||||||
result.append(self._receive_rpc_value(tag))
|
result.append(self._receive_rpc_value(tag, rpc_map))
|
||||||
|
|
||||||
def _serve_rpc(self, rpc_map):
|
def _serve_rpc(self, rpc_map):
|
||||||
service = self._read_int32()
|
service = self._read_int32()
|
||||||
args = self._receive_rpc_values()
|
args = self._receive_rpc_values(rpc_map)
|
||||||
logger.debug("rpc service: %d %r", service, args)
|
logger.debug("rpc service: %d %r", service, args)
|
||||||
|
|
||||||
eid, result = rpc_wrapper.run_rpc(rpc_map[rpc_num], args)
|
try:
|
||||||
logger.debug("rpc service: %d %r == %r (eid %d)", service, args,
|
result = rpc_map[rpc_num](args)
|
||||||
result, eid)
|
if not isinstance(result, int) or not (-2**31 < result < 2**31-1):
|
||||||
|
raise ValueError("An RPC must return an int(width=32)")
|
||||||
|
except ARTIQException as exn:
|
||||||
|
logger.debug("rpc service: %d %r ! %r", service, args, exn)
|
||||||
|
|
||||||
|
self._write_header(_H2DMsgType.RPC_EXCEPTION)
|
||||||
|
self._write_string(exn.name)
|
||||||
|
self._write_string(exn.message)
|
||||||
|
for index in range(3):
|
||||||
|
self._write_int64(exn.param[index])
|
||||||
|
|
||||||
|
self._write_string(exn.filename)
|
||||||
|
self._write_int32(exn.line)
|
||||||
|
self._write_int32(exn.column)
|
||||||
|
self._write_string(exn.function)
|
||||||
|
|
||||||
|
self._write_flush()
|
||||||
|
except Exception as exn:
|
||||||
|
logger.debug("rpc service: %d %r ! %r", service, args, exn)
|
||||||
|
|
||||||
|
self._write_header(_H2DMsgType.RPC_EXCEPTION)
|
||||||
|
self._write_string(type(exn).__name__)
|
||||||
|
self._write_string(str(exn))
|
||||||
|
for index in range(3):
|
||||||
|
self._write_int64(0)
|
||||||
|
|
||||||
|
((filename, line, function, _), ) = traceback.extract_tb(exn.__traceback__)
|
||||||
|
self._write_string(filename)
|
||||||
|
self._write_int32(line)
|
||||||
|
self._write_int32(-1) # column not known
|
||||||
|
self._write_string(function)
|
||||||
|
|
||||||
|
self._write_flush()
|
||||||
|
else:
|
||||||
|
logger.debug("rpc service: %d %r == %r", service, args, result)
|
||||||
|
|
||||||
self._write_header(_H2DMsgType.RPC_REPLY)
|
self._write_header(_H2DMsgType.RPC_REPLY)
|
||||||
self._write_int32(eid)
|
|
||||||
self._write_int32(result)
|
self._write_int32(result)
|
||||||
self._write_flush()
|
self._write_flush()
|
||||||
|
|
||||||
def _serve_exception(self):
|
def _serve_exception(self):
|
||||||
eid = self._read_int32()
|
name = self._read_string()
|
||||||
|
message = self._read_string()
|
||||||
params = [self._read_int64() for _ in range(3)]
|
params = [self._read_int64() for _ in range(3)]
|
||||||
rpc_wrapper.filter_rpc_exception(eid)
|
|
||||||
raise exception(self.core, *params)
|
filename = self._read_string()
|
||||||
|
line = self._read_int32()
|
||||||
|
column = self._read_int32()
|
||||||
|
function = self._read_string()
|
||||||
|
|
||||||
|
backtrace = [self._read_int32() for _ in range(self._read_int32())]
|
||||||
|
# we don't have debug information yet.
|
||||||
|
# print("exception backtrace:", [hex(x) for x in backtrace])
|
||||||
|
|
||||||
|
raise core_language.ARTIQException(name, message, params,
|
||||||
|
filename, line, column, function)
|
||||||
|
|
||||||
def serve(self, rpc_map):
|
def serve(self, rpc_map):
|
||||||
while True:
|
while True:
|
||||||
@ -328,10 +383,3 @@ class CommGeneric:
|
|||||||
else:
|
else:
|
||||||
self._read_expect(_D2HMsgType.KERNEL_FINISHED)
|
self._read_expect(_D2HMsgType.KERNEL_FINISHED)
|
||||||
return
|
return
|
||||||
|
|
||||||
def get_log(self):
|
|
||||||
self._write_empty(_H2DMsgType.LOG_REQUEST)
|
|
||||||
|
|
||||||
self._read_header()
|
|
||||||
self._read_expect(_D2HMsgType.LOG_REPLY)
|
|
||||||
return self._read_chunk(self._read_length).decode('utf-8')
|
|
||||||
|
@ -1,5 +1,13 @@
|
|||||||
from artiq.language.core import ARTIQException
|
from artiq.language.core import ARTIQException
|
||||||
|
|
||||||
|
class ZeroDivisionError(ARTIQException):
|
||||||
|
"""Python's :class:`ZeroDivisionError`, mirrored in ARTIQ."""
|
||||||
|
|
||||||
|
class ValueError(ARTIQException):
|
||||||
|
"""Python's :class:`ValueError`, mirrored in ARTIQ."""
|
||||||
|
|
||||||
|
class IndexError(ARTIQException):
|
||||||
|
"""Python's :class:`IndexError`, mirrored in ARTIQ."""
|
||||||
|
|
||||||
class InternalError(ARTIQException):
|
class InternalError(ARTIQException):
|
||||||
"""Raised when the runtime encounters an internal error condition."""
|
"""Raised when the runtime encounters an internal error condition."""
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
Core ARTIQ extensions to the Python language.
|
Core ARTIQ extensions to the Python language.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
import linecache
|
||||||
from collections import namedtuple
|
from collections import namedtuple
|
||||||
from functools import wraps
|
from functools import wraps
|
||||||
|
|
||||||
@ -278,7 +279,8 @@ class ARTIQException(Exception):
|
|||||||
"""Base class for exceptions raised or passed through the core device."""
|
"""Base class for exceptions raised or passed through the core device."""
|
||||||
|
|
||||||
# Try and create an instance of the specific class, if one exists.
|
# Try and create an instance of the specific class, if one exists.
|
||||||
def __new__(cls, name, message, params):
|
def __new__(cls, name, message,
|
||||||
|
params, filename, line, column, function):
|
||||||
def find_subclass(cls):
|
def find_subclass(cls):
|
||||||
if cls.__name__ == name:
|
if cls.__name__ == name:
|
||||||
return cls
|
return cls
|
||||||
@ -293,15 +295,30 @@ class ARTIQException(Exception):
|
|||||||
more_specific_cls = cls
|
more_specific_cls = cls
|
||||||
|
|
||||||
exn = Exception.__new__(more_specific_cls)
|
exn = Exception.__new__(more_specific_cls)
|
||||||
exn.__init__(name, message, params)
|
exn.__init__(name, message, params,
|
||||||
|
filename, line, column, function)
|
||||||
return exn
|
return exn
|
||||||
|
|
||||||
def __init__(self, name, message, params):
|
def __init__(self, name, message, params,
|
||||||
|
filename, line, column, function):
|
||||||
Exception.__init__(self, name, message, *params)
|
Exception.__init__(self, name, message, *params)
|
||||||
self.name, self.message, self.params = name, message, params
|
self.name, self.message, self.params = name, message, params
|
||||||
|
self.filename, self.line, self.column = filename, line, column
|
||||||
|
self.function = function
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
|
lines = []
|
||||||
|
|
||||||
if type(self).__name__ == self.name:
|
if type(self).__name__ == self.name:
|
||||||
return self.message.format(*self.params)
|
lines.append(self.message.format(*self.params))
|
||||||
else:
|
else:
|
||||||
return "({}) {}".format(self.name, self.message.format(*self.params))
|
lines.append("({}) {}".format(self.name, self.message.format(*self.params)))
|
||||||
|
|
||||||
|
lines.append("Core Device Traceback (most recent call last):")
|
||||||
|
lines.append(" File \"{file}\", line {line}, column {column}, in {function}".
|
||||||
|
format(file=self.filename, line=self.line, column=self.column + 1,
|
||||||
|
function=self.function))
|
||||||
|
line = linecache.getline(self.filename, self.line)
|
||||||
|
lines.append(" {}".format(line.strip() if line else "<unknown>"))
|
||||||
|
|
||||||
|
return "\n".join(lines)
|
||||||
|
@ -12,6 +12,7 @@ struct artiq_exception {
|
|||||||
const char *file;
|
const char *file;
|
||||||
int32_t line;
|
int32_t line;
|
||||||
int32_t column;
|
int32_t column;
|
||||||
|
const char *function;
|
||||||
const char *message;
|
const char *message;
|
||||||
int64_t param[3];
|
int64_t param[3];
|
||||||
};
|
};
|
||||||
|
@ -30,7 +30,7 @@ void kloader_start_bridge()
|
|||||||
start_kernel_cpu(NULL);
|
start_kernel_cpu(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int load_or_start_kernel(void *library, int run_kernel)
|
static int load_or_start_kernel(const void *library, int run_kernel)
|
||||||
{
|
{
|
||||||
static struct dyld_info library_info;
|
static struct dyld_info library_info;
|
||||||
struct msg_load_request request = {
|
struct msg_load_request request = {
|
||||||
@ -56,7 +56,7 @@ static int load_or_start_kernel(void *library, int run_kernel)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int kloader_load_library(void *library)
|
int kloader_load_library(const void *library)
|
||||||
{
|
{
|
||||||
if(!kernel_cpu_reset_read()) {
|
if(!kernel_cpu_reset_read()) {
|
||||||
log("BUG: attempted to load kernel library while kernel CPU is running");
|
log("BUG: attempted to load kernel library while kernel CPU is running");
|
||||||
@ -66,6 +66,22 @@ int kloader_load_library(void *library)
|
|||||||
return load_or_start_kernel(library, 0);
|
return load_or_start_kernel(library, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void kloader_filter_backtrace(struct artiq_backtrace_item *backtrace,
|
||||||
|
size_t *backtrace_size) {
|
||||||
|
struct artiq_backtrace_item *cursor = backtrace;
|
||||||
|
|
||||||
|
// Remove all backtrace items belonging to ksupport and subtract
|
||||||
|
// shared object base from the addresses.
|
||||||
|
for(int i = 0; i < *backtrace_size; i++) {
|
||||||
|
if(backtrace[i].function > KERNELCPU_PAYLOAD_ADDRESS) {
|
||||||
|
backtrace[i].function -= KERNELCPU_PAYLOAD_ADDRESS;
|
||||||
|
*cursor++ = backtrace[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
*backtrace_size = cursor - backtrace;
|
||||||
|
}
|
||||||
|
|
||||||
void kloader_start_kernel()
|
void kloader_start_kernel()
|
||||||
{
|
{
|
||||||
load_or_start_kernel(NULL, 1);
|
load_or_start_kernel(NULL, 1);
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
#ifndef __KLOADER_H
|
#ifndef __KLOADER_H
|
||||||
#define __KLOADER_H
|
#define __KLOADER_H
|
||||||
|
|
||||||
|
#include "artiq_personality.h"
|
||||||
|
|
||||||
#define KERNELCPU_EXEC_ADDRESS 0x40400000
|
#define KERNELCPU_EXEC_ADDRESS 0x40400000
|
||||||
#define KERNELCPU_PAYLOAD_ADDRESS 0x40420000
|
#define KERNELCPU_PAYLOAD_ADDRESS 0x40420000
|
||||||
#define KERNELCPU_LAST_ADDRESS (0x4fffffff - 1024*1024)
|
#define KERNELCPU_LAST_ADDRESS (0x4fffffff - 1024*1024)
|
||||||
@ -8,7 +10,9 @@
|
|||||||
|
|
||||||
extern long long int now;
|
extern long long int now;
|
||||||
|
|
||||||
int kloader_load_library(void *code);
|
int kloader_load_library(const void *code);
|
||||||
|
void kloader_filter_backtrace(struct artiq_backtrace_item *backtrace,
|
||||||
|
size_t *backtrace_size);
|
||||||
|
|
||||||
void kloader_start_bridge(void);
|
void kloader_start_bridge(void);
|
||||||
int kloader_start_idle_kernel(void);
|
int kloader_start_idle_kernel(void);
|
||||||
|
@ -246,7 +246,8 @@ long long int now_init(void)
|
|||||||
|
|
||||||
reply = mailbox_wait_and_receive();
|
reply = mailbox_wait_and_receive();
|
||||||
if(reply->type != MESSAGE_TYPE_NOW_INIT_REPLY) {
|
if(reply->type != MESSAGE_TYPE_NOW_INIT_REPLY) {
|
||||||
log("Malformed MESSAGE_TYPE_NOW_INIT_REQUEST reply type");
|
log("Malformed MESSAGE_TYPE_NOW_INIT_REQUEST reply type %d",
|
||||||
|
reply->type);
|
||||||
while(1);
|
while(1);
|
||||||
}
|
}
|
||||||
now = reply->now;
|
now = reply->now;
|
||||||
@ -281,7 +282,8 @@ int watchdog_set(int ms)
|
|||||||
|
|
||||||
reply = mailbox_wait_and_receive();
|
reply = mailbox_wait_and_receive();
|
||||||
if(reply->type != MESSAGE_TYPE_WATCHDOG_SET_REPLY) {
|
if(reply->type != MESSAGE_TYPE_WATCHDOG_SET_REPLY) {
|
||||||
log("Malformed MESSAGE_TYPE_WATCHDOG_SET_REQUEST reply type");
|
log("Malformed MESSAGE_TYPE_WATCHDOG_SET_REQUEST reply type %d",
|
||||||
|
reply->type);
|
||||||
while(1);
|
while(1);
|
||||||
}
|
}
|
||||||
id = reply->id;
|
id = reply->id;
|
||||||
@ -302,7 +304,7 @@ void watchdog_clear(int id)
|
|||||||
int rpc(int rpc_num, ...)
|
int rpc(int rpc_num, ...)
|
||||||
{
|
{
|
||||||
struct msg_rpc_request request;
|
struct msg_rpc_request request;
|
||||||
struct msg_rpc_reply *reply;
|
struct msg_base *reply;
|
||||||
|
|
||||||
request.type = MESSAGE_TYPE_RPC_REQUEST;
|
request.type = MESSAGE_TYPE_RPC_REQUEST;
|
||||||
request.rpc_num = rpc_num;
|
request.rpc_num = rpc_num;
|
||||||
@ -311,20 +313,20 @@ int rpc(int rpc_num, ...)
|
|||||||
va_end(request.args);
|
va_end(request.args);
|
||||||
|
|
||||||
reply = mailbox_wait_and_receive();
|
reply = mailbox_wait_and_receive();
|
||||||
if(reply->type != MESSAGE_TYPE_RPC_REPLY) {
|
if(reply->type == MESSAGE_TYPE_RPC_REPLY) {
|
||||||
log("Malformed MESSAGE_TYPE_RPC_REPLY reply type");
|
int result = ((struct msg_rpc_reply *)reply)->result;
|
||||||
while(1);
|
mailbox_acknowledge();
|
||||||
}
|
return result;
|
||||||
|
} else if(reply->type == MESSAGE_TYPE_RPC_EXCEPTION) {
|
||||||
if(reply->exception != NULL) {
|
|
||||||
struct artiq_exception exception;
|
struct artiq_exception exception;
|
||||||
memcpy(&exception, reply->exception, sizeof(exception));
|
memcpy(&exception, ((struct msg_rpc_exception *)reply)->exception,
|
||||||
|
sizeof(struct artiq_exception));
|
||||||
mailbox_acknowledge();
|
mailbox_acknowledge();
|
||||||
__artiq_raise(&exception);
|
__artiq_raise(&exception);
|
||||||
} else {
|
} else {
|
||||||
int retval = reply->retval;
|
log("Malformed MESSAGE_TYPE_RPC_REQUEST reply type %d",
|
||||||
mailbox_acknowledge();
|
reply->type);
|
||||||
return retval;
|
while(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,6 +16,7 @@ enum {
|
|||||||
MESSAGE_TYPE_WATCHDOG_CLEAR,
|
MESSAGE_TYPE_WATCHDOG_CLEAR,
|
||||||
MESSAGE_TYPE_RPC_REQUEST,
|
MESSAGE_TYPE_RPC_REQUEST,
|
||||||
MESSAGE_TYPE_RPC_REPLY,
|
MESSAGE_TYPE_RPC_REPLY,
|
||||||
|
MESSAGE_TYPE_RPC_EXCEPTION,
|
||||||
MESSAGE_TYPE_LOG,
|
MESSAGE_TYPE_LOG,
|
||||||
|
|
||||||
MESSAGE_TYPE_BRG_READY,
|
MESSAGE_TYPE_BRG_READY,
|
||||||
@ -37,7 +38,7 @@ struct msg_base {
|
|||||||
/* kernel messages */
|
/* kernel messages */
|
||||||
|
|
||||||
struct msg_load_request {
|
struct msg_load_request {
|
||||||
void *library;
|
const void *library;
|
||||||
struct dyld_info *library_info;
|
struct dyld_info *library_info;
|
||||||
int run_kernel;
|
int run_kernel;
|
||||||
};
|
};
|
||||||
@ -86,9 +87,13 @@ struct msg_rpc_request {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct msg_rpc_reply {
|
struct msg_rpc_reply {
|
||||||
|
int type;
|
||||||
|
int result;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct msg_rpc_exception {
|
||||||
int type;
|
int type;
|
||||||
struct artiq_exception *exception;
|
struct artiq_exception *exception;
|
||||||
int retval;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct msg_log {
|
struct msg_log {
|
||||||
|
@ -128,6 +128,13 @@ static int32_t in_packet_int32()
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int64_t in_packet_int64()
|
||||||
|
{
|
||||||
|
int64_t result;
|
||||||
|
in_packet_chunk(&result, sizeof(result));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
static const void *in_packet_bytes(int *length)
|
static const void *in_packet_bytes(int *length)
|
||||||
{
|
{
|
||||||
*length = in_packet_int32();
|
*length = in_packet_int32();
|
||||||
@ -310,6 +317,7 @@ enum {
|
|||||||
REMOTEMSG_TYPE_RUN_KERNEL,
|
REMOTEMSG_TYPE_RUN_KERNEL,
|
||||||
|
|
||||||
REMOTEMSG_TYPE_RPC_REPLY,
|
REMOTEMSG_TYPE_RPC_REPLY,
|
||||||
|
REMOTEMSG_TYPE_RPC_EXCEPTION,
|
||||||
|
|
||||||
REMOTEMSG_TYPE_FLASH_READ_REQUEST,
|
REMOTEMSG_TYPE_FLASH_READ_REQUEST,
|
||||||
REMOTEMSG_TYPE_FLASH_WRITE_REQUEST,
|
REMOTEMSG_TYPE_FLASH_WRITE_REQUEST,
|
||||||
@ -452,15 +460,44 @@ static int process_input(void)
|
|||||||
case REMOTEMSG_TYPE_RPC_REPLY: {
|
case REMOTEMSG_TYPE_RPC_REPLY: {
|
||||||
struct msg_rpc_reply reply;
|
struct msg_rpc_reply reply;
|
||||||
|
|
||||||
|
int result = in_packet_int32();
|
||||||
|
|
||||||
if(user_kernel_state != USER_KERNEL_WAIT_RPC) {
|
if(user_kernel_state != USER_KERNEL_WAIT_RPC) {
|
||||||
log("Unsolicited RPC reply");
|
log("Unsolicited RPC reply");
|
||||||
return 0; // restart session
|
return 0; // restart session
|
||||||
}
|
}
|
||||||
|
|
||||||
reply.type = MESSAGE_TYPE_RPC_REPLY;
|
reply.type = MESSAGE_TYPE_RPC_REPLY;
|
||||||
// FIXME memcpy(&reply.eid, &buffer_in[9], 4);
|
reply.result = result;
|
||||||
// memcpy(&reply.retval, &buffer_in[13], 4);
|
|
||||||
mailbox_send_and_wait(&reply);
|
mailbox_send_and_wait(&reply);
|
||||||
|
|
||||||
|
user_kernel_state = USER_KERNEL_RUNNING;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case REMOTEMSG_TYPE_RPC_EXCEPTION: {
|
||||||
|
struct msg_rpc_exception reply;
|
||||||
|
|
||||||
|
struct artiq_exception exception;
|
||||||
|
exception.name = in_packet_string();
|
||||||
|
exception.message = in_packet_string();
|
||||||
|
exception.param[0] = in_packet_int64();
|
||||||
|
exception.param[1] = in_packet_int64();
|
||||||
|
exception.param[2] = in_packet_int64();
|
||||||
|
exception.file = in_packet_string();
|
||||||
|
exception.line = in_packet_int32();
|
||||||
|
exception.column = in_packet_int32();
|
||||||
|
exception.function = in_packet_string();
|
||||||
|
|
||||||
|
if(user_kernel_state != USER_KERNEL_WAIT_RPC) {
|
||||||
|
log("Unsolicited RPC exception reply");
|
||||||
|
return 0; // restart session
|
||||||
|
}
|
||||||
|
|
||||||
|
reply.type = MESSAGE_TYPE_RPC_EXCEPTION;
|
||||||
|
reply.exception = &exception;
|
||||||
|
mailbox_send_and_wait(&reply);
|
||||||
|
|
||||||
user_kernel_state = USER_KERNEL_RUNNING;
|
user_kernel_state = USER_KERNEL_RUNNING;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -509,8 +546,6 @@ static int send_rpc_value(const char **tag, void *value)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case 'l': { // list(elt='a)
|
case 'l': { // list(elt='a)
|
||||||
size = sizeof(void*);
|
|
||||||
|
|
||||||
struct { uint32_t length; void *elements; } *list = value;
|
struct { uint32_t length; void *elements; } *list = value;
|
||||||
void *element = list->elements;
|
void *element = list->elements;
|
||||||
|
|
||||||
@ -522,6 +557,18 @@ static int send_rpc_value(const char **tag, void *value)
|
|||||||
element = (void*)((intptr_t)element + element_size);
|
element = (void*)((intptr_t)element + element_size);
|
||||||
}
|
}
|
||||||
*tag = tag_copy;
|
*tag = tag_copy;
|
||||||
|
|
||||||
|
size = sizeof(list);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case 'o': { // host object
|
||||||
|
struct { uint32_t id; } *object = value;
|
||||||
|
|
||||||
|
if(!out_packet_int32(object->id))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
size = sizeof(object);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -575,10 +622,29 @@ static int process_kmsg(struct msg_base *umsg)
|
|||||||
case MESSAGE_TYPE_EXCEPTION: {
|
case MESSAGE_TYPE_EXCEPTION: {
|
||||||
struct msg_exception *msg = (struct msg_exception *)umsg;
|
struct msg_exception *msg = (struct msg_exception *)umsg;
|
||||||
|
|
||||||
out_packet_empty(REMOTEMSG_TYPE_KERNEL_EXCEPTION);
|
out_packet_start(REMOTEMSG_TYPE_KERNEL_EXCEPTION);
|
||||||
// memcpy(&buffer_out[9], &msg->eid, 4);
|
|
||||||
// memcpy(&buffer_out[13], msg->eparams, 3*8);
|
out_packet_string(msg->exception->name);
|
||||||
// submit_output(9+4+3*8);
|
out_packet_string(msg->exception->message);
|
||||||
|
out_packet_int64(msg->exception->param[0]);
|
||||||
|
out_packet_int64(msg->exception->param[1]);
|
||||||
|
out_packet_int64(msg->exception->param[2]);
|
||||||
|
|
||||||
|
out_packet_string(msg->exception->file);
|
||||||
|
out_packet_int32(msg->exception->line);
|
||||||
|
out_packet_int32(msg->exception->column);
|
||||||
|
out_packet_string(msg->exception->function);
|
||||||
|
|
||||||
|
kloader_filter_backtrace(msg->backtrace,
|
||||||
|
&msg->backtrace_size);
|
||||||
|
|
||||||
|
out_packet_int32(msg->backtrace_size);
|
||||||
|
for(int i = 0; i < msg->backtrace_size; i++) {
|
||||||
|
struct artiq_backtrace_item *item = &msg->backtrace[i];
|
||||||
|
out_packet_int32(item->function + item->offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
out_packet_finish();
|
||||||
|
|
||||||
kloader_stop();
|
kloader_stop();
|
||||||
user_kernel_state = USER_KERNEL_LOADED;
|
user_kernel_state = USER_KERNEL_LOADED;
|
||||||
|
Loading…
Reference in New Issue
Block a user