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()),
|
||||
("__line__", TInt(types.TValue(32))),
|
||||
("__col__", TInt(types.TValue(32))),
|
||||
("__func__", TStr()),
|
||||
("__message__", TStr()),
|
||||
("__param0__", 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):
|
||||
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()
|
||||
else:
|
||||
name = node.name
|
||||
@ -471,9 +471,11 @@ class ARTIQIRGenerator(algorithm.Visitor):
|
||||
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_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, "__line__", loc_line))
|
||||
self.append(ir.SetAttr(exn, "__col__", loc_column))
|
||||
self.append(ir.SetAttr(exn, "__func__", loc_function))
|
||||
|
||||
if self.unwind_target is not None:
|
||||
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(0, builtins.TInt(types.TValue(32))), # line
|
||||
ir.Constant(0, builtins.TInt(types.TValue(32))), # column
|
||||
ir.Constant("<not thrown>", builtins.TStr()), # function
|
||||
]
|
||||
|
||||
if message is None:
|
||||
|
@ -1,5 +1,6 @@
|
||||
import struct
|
||||
import logging
|
||||
import traceback
|
||||
from enum import Enum
|
||||
from fractions import Fraction
|
||||
|
||||
@ -18,11 +19,12 @@ class _H2DMsgType(Enum):
|
||||
RUN_KERNEL = 5
|
||||
|
||||
RPC_REPLY = 6
|
||||
RPC_EXCEPTION = 7
|
||||
|
||||
FLASH_READ_REQUEST = 7
|
||||
FLASH_WRITE_REQUEST = 8
|
||||
FLASH_ERASE_REQUEST = 9
|
||||
FLASH_REMOVE_REQUEST = 10
|
||||
FLASH_READ_REQUEST = 8
|
||||
FLASH_WRITE_REQUEST = 9
|
||||
FLASH_ERASE_REQUEST = 10
|
||||
FLASH_REMOVE_REQUEST = 11
|
||||
|
||||
|
||||
class _D2HMsgType(Enum):
|
||||
@ -223,16 +225,12 @@ class CommGeneric:
|
||||
|
||||
self._read_empty(_D2HMsgType.CLOCK_SWITCH_COMPLETED)
|
||||
|
||||
def load(self, kernel_library):
|
||||
self._write_header(_H2DMsgType.LOAD_LIBRARY)
|
||||
self._write_chunk(kernel_library)
|
||||
self._write_flush()
|
||||
def get_log(self):
|
||||
self._write_empty(_H2DMsgType.LOG_REQUEST)
|
||||
|
||||
self._read_empty(_D2HMsgType.LOAD_COMPLETED)
|
||||
|
||||
def run(self):
|
||||
self._write_empty(_H2DMsgType.RUN_KERNEL)
|
||||
logger.debug("running kernel")
|
||||
self._read_header()
|
||||
self._read_expect(_D2HMsgType.LOG_REPLY)
|
||||
return self._read_chunk(self._read_length).decode('utf-8')
|
||||
|
||||
def flash_storage_read(self, key):
|
||||
self._write_header(_H2DMsgType.FLASH_READ_REQUEST)
|
||||
@ -267,7 +265,18 @@ class CommGeneric:
|
||||
|
||||
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":
|
||||
return None
|
||||
elif tag == "b":
|
||||
@ -286,37 +295,83 @@ class CommGeneric:
|
||||
elt_tag = chr(self._read_int8())
|
||||
length = self._read_int32()
|
||||
return [self._receive_rpc_value(elt_tag) for _ in range(length)]
|
||||
elif tag == "o":
|
||||
return rpc_map[self._read_int32()]
|
||||
else:
|
||||
raise IOError("Unknown RPC value tag: {}", tag)
|
||||
|
||||
def _receive_rpc_values(self):
|
||||
def _receive_rpc_values(self, rpc_map):
|
||||
result = []
|
||||
while True:
|
||||
tag = chr(self._read_int8())
|
||||
if tag == "\x00":
|
||||
return result
|
||||
else:
|
||||
result.append(self._receive_rpc_value(tag))
|
||||
result.append(self._receive_rpc_value(tag, rpc_map))
|
||||
|
||||
def _serve_rpc(self, rpc_map):
|
||||
service = self._read_int32()
|
||||
args = self._receive_rpc_values()
|
||||
args = self._receive_rpc_values(rpc_map)
|
||||
logger.debug("rpc service: %d %r", service, args)
|
||||
|
||||
eid, result = rpc_wrapper.run_rpc(rpc_map[rpc_num], args)
|
||||
logger.debug("rpc service: %d %r == %r (eid %d)", service, args,
|
||||
result, eid)
|
||||
try:
|
||||
result = rpc_map[rpc_num](args)
|
||||
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_REPLY)
|
||||
self._write_int32(eid)
|
||||
self._write_int32(result)
|
||||
self._write_flush()
|
||||
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_int32(result)
|
||||
self._write_flush()
|
||||
|
||||
def _serve_exception(self):
|
||||
eid = self._read_int32()
|
||||
params = [self._read_int64() for _ in range(3)]
|
||||
rpc_wrapper.filter_rpc_exception(eid)
|
||||
raise exception(self.core, *params)
|
||||
name = self._read_string()
|
||||
message = self._read_string()
|
||||
params = [self._read_int64() for _ in range(3)]
|
||||
|
||||
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):
|
||||
while True:
|
||||
@ -328,10 +383,3 @@ class CommGeneric:
|
||||
else:
|
||||
self._read_expect(_D2HMsgType.KERNEL_FINISHED)
|
||||
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
|
||||
|
||||
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):
|
||||
"""Raised when the runtime encounters an internal error condition."""
|
||||
|
@ -2,6 +2,7 @@
|
||||
Core ARTIQ extensions to the Python language.
|
||||
"""
|
||||
|
||||
import linecache
|
||||
from collections import namedtuple
|
||||
from functools import wraps
|
||||
|
||||
@ -278,7 +279,8 @@ class ARTIQException(Exception):
|
||||
"""Base class for exceptions raised or passed through the core device."""
|
||||
|
||||
# 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):
|
||||
if cls.__name__ == name:
|
||||
return cls
|
||||
@ -293,15 +295,30 @@ class ARTIQException(Exception):
|
||||
more_specific_cls = cls
|
||||
|
||||
exn = Exception.__new__(more_specific_cls)
|
||||
exn.__init__(name, message, params)
|
||||
exn.__init__(name, message, params,
|
||||
filename, line, column, function)
|
||||
return exn
|
||||
|
||||
def __init__(self, name, message, params):
|
||||
def __init__(self, name, message, params,
|
||||
filename, line, column, function):
|
||||
Exception.__init__(self, 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):
|
||||
lines = []
|
||||
|
||||
if type(self).__name__ == self.name:
|
||||
return self.message.format(*self.params)
|
||||
lines.append(self.message.format(*self.params))
|
||||
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;
|
||||
int32_t line;
|
||||
int32_t column;
|
||||
const char *function;
|
||||
const char *message;
|
||||
int64_t param[3];
|
||||
};
|
||||
|
@ -30,7 +30,7 @@ void kloader_start_bridge()
|
||||
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;
|
||||
struct msg_load_request request = {
|
||||
@ -56,7 +56,7 @@ static int load_or_start_kernel(void *library, int run_kernel)
|
||||
return 1;
|
||||
}
|
||||
|
||||
int kloader_load_library(void *library)
|
||||
int kloader_load_library(const void *library)
|
||||
{
|
||||
if(!kernel_cpu_reset_read()) {
|
||||
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);
|
||||
}
|
||||
|
||||
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()
|
||||
{
|
||||
load_or_start_kernel(NULL, 1);
|
||||
|
@ -1,6 +1,8 @@
|
||||
#ifndef __KLOADER_H
|
||||
#define __KLOADER_H
|
||||
|
||||
#include "artiq_personality.h"
|
||||
|
||||
#define KERNELCPU_EXEC_ADDRESS 0x40400000
|
||||
#define KERNELCPU_PAYLOAD_ADDRESS 0x40420000
|
||||
#define KERNELCPU_LAST_ADDRESS (0x4fffffff - 1024*1024)
|
||||
@ -8,7 +10,9 @@
|
||||
|
||||
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);
|
||||
int kloader_start_idle_kernel(void);
|
||||
|
@ -246,7 +246,8 @@ long long int now_init(void)
|
||||
|
||||
reply = mailbox_wait_and_receive();
|
||||
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);
|
||||
}
|
||||
now = reply->now;
|
||||
@ -281,7 +282,8 @@ int watchdog_set(int ms)
|
||||
|
||||
reply = mailbox_wait_and_receive();
|
||||
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);
|
||||
}
|
||||
id = reply->id;
|
||||
@ -302,7 +304,7 @@ void watchdog_clear(int id)
|
||||
int rpc(int rpc_num, ...)
|
||||
{
|
||||
struct msg_rpc_request request;
|
||||
struct msg_rpc_reply *reply;
|
||||
struct msg_base *reply;
|
||||
|
||||
request.type = MESSAGE_TYPE_RPC_REQUEST;
|
||||
request.rpc_num = rpc_num;
|
||||
@ -311,20 +313,20 @@ int rpc(int rpc_num, ...)
|
||||
va_end(request.args);
|
||||
|
||||
reply = mailbox_wait_and_receive();
|
||||
if(reply->type != MESSAGE_TYPE_RPC_REPLY) {
|
||||
log("Malformed MESSAGE_TYPE_RPC_REPLY reply type");
|
||||
while(1);
|
||||
}
|
||||
|
||||
if(reply->exception != NULL) {
|
||||
if(reply->type == MESSAGE_TYPE_RPC_REPLY) {
|
||||
int result = ((struct msg_rpc_reply *)reply)->result;
|
||||
mailbox_acknowledge();
|
||||
return result;
|
||||
} else if(reply->type == MESSAGE_TYPE_RPC_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();
|
||||
__artiq_raise(&exception);
|
||||
} else {
|
||||
int retval = reply->retval;
|
||||
mailbox_acknowledge();
|
||||
return retval;
|
||||
log("Malformed MESSAGE_TYPE_RPC_REQUEST reply type %d",
|
||||
reply->type);
|
||||
while(1);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -16,6 +16,7 @@ enum {
|
||||
MESSAGE_TYPE_WATCHDOG_CLEAR,
|
||||
MESSAGE_TYPE_RPC_REQUEST,
|
||||
MESSAGE_TYPE_RPC_REPLY,
|
||||
MESSAGE_TYPE_RPC_EXCEPTION,
|
||||
MESSAGE_TYPE_LOG,
|
||||
|
||||
MESSAGE_TYPE_BRG_READY,
|
||||
@ -37,7 +38,7 @@ struct msg_base {
|
||||
/* kernel messages */
|
||||
|
||||
struct msg_load_request {
|
||||
void *library;
|
||||
const void *library;
|
||||
struct dyld_info *library_info;
|
||||
int run_kernel;
|
||||
};
|
||||
@ -86,9 +87,13 @@ struct msg_rpc_request {
|
||||
};
|
||||
|
||||
struct msg_rpc_reply {
|
||||
int type;
|
||||
int result;
|
||||
};
|
||||
|
||||
struct msg_rpc_exception {
|
||||
int type;
|
||||
struct artiq_exception *exception;
|
||||
int retval;
|
||||
};
|
||||
|
||||
struct msg_log {
|
||||
|
@ -128,6 +128,13 @@ static int32_t in_packet_int32()
|
||||
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)
|
||||
{
|
||||
*length = in_packet_int32();
|
||||
@ -310,6 +317,7 @@ enum {
|
||||
REMOTEMSG_TYPE_RUN_KERNEL,
|
||||
|
||||
REMOTEMSG_TYPE_RPC_REPLY,
|
||||
REMOTEMSG_TYPE_RPC_EXCEPTION,
|
||||
|
||||
REMOTEMSG_TYPE_FLASH_READ_REQUEST,
|
||||
REMOTEMSG_TYPE_FLASH_WRITE_REQUEST,
|
||||
@ -452,15 +460,44 @@ static int process_input(void)
|
||||
case REMOTEMSG_TYPE_RPC_REPLY: {
|
||||
struct msg_rpc_reply reply;
|
||||
|
||||
int result = in_packet_int32();
|
||||
|
||||
if(user_kernel_state != USER_KERNEL_WAIT_RPC) {
|
||||
log("Unsolicited RPC reply");
|
||||
return 0; // restart session
|
||||
}
|
||||
|
||||
reply.type = MESSAGE_TYPE_RPC_REPLY;
|
||||
// FIXME memcpy(&reply.eid, &buffer_in[9], 4);
|
||||
// memcpy(&reply.retval, &buffer_in[13], 4);
|
||||
reply.result = result;
|
||||
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;
|
||||
break;
|
||||
}
|
||||
@ -509,8 +546,6 @@ static int send_rpc_value(const char **tag, void *value)
|
||||
break;
|
||||
|
||||
case 'l': { // list(elt='a)
|
||||
size = sizeof(void*);
|
||||
|
||||
struct { uint32_t length; void *elements; } *list = value;
|
||||
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);
|
||||
}
|
||||
*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;
|
||||
}
|
||||
|
||||
@ -575,10 +622,29 @@ static int process_kmsg(struct msg_base *umsg)
|
||||
case MESSAGE_TYPE_EXCEPTION: {
|
||||
struct msg_exception *msg = (struct msg_exception *)umsg;
|
||||
|
||||
out_packet_empty(REMOTEMSG_TYPE_KERNEL_EXCEPTION);
|
||||
// memcpy(&buffer_out[9], &msg->eid, 4);
|
||||
// memcpy(&buffer_out[13], msg->eparams, 3*8);
|
||||
// submit_output(9+4+3*8);
|
||||
out_packet_start(REMOTEMSG_TYPE_KERNEL_EXCEPTION);
|
||||
|
||||
out_packet_string(msg->exception->name);
|
||||
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();
|
||||
user_kernel_state = USER_KERNEL_LOADED;
|
||||
|
Loading…
Reference in New Issue
Block a user