/****************************************************************************** * tools/xenbaked.c * * Tool for collecting raw trace buffer data from Xen and * performing some accumulation operations and other processing * on it. * * Copyright (C) 2004 by Intel Research Cambridge * Copyright (C) 2005 by Hewlett Packard, Palo Alto and Fort Collins * Copyright (C) 2006 by Hewlett Packard Fort Collins * * Authors: Diwaker Gupta, diwaker.gupta@hp.com * Rob Gardner, rob.gardner@hp.com * Lucy Cherkasova, lucy.cherkasova.hp.com * Much code based on xentrace, authored by Mark Williamson, mark.a.williamson@intel.com * Date: November, 2005 * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; under version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define PERROR(_m, _a...) \ do { \ int __saved_errno = errno; \ fprintf(stderr, "ERROR: " _m " (%d = %s)\n" , ## _a , \ __saved_errno, strerror(__saved_errno)); \ errno = __saved_errno; \ } while (0) typedef struct { int counter; } atomic_t; #define _atomic_read(v) ((v).counter) #include #include "xenbaked.h" extern FILE *stderr; /***** Compile time configuration of defaults ********************************/ /* when we've got more records than this waiting, we log it to the output */ #define NEW_DATA_THRESH 1 /* sleep for this long (milliseconds) between checking the trace buffers */ #define POLL_SLEEP_MILLIS 100 /* Size of time period represented by each sample */ #define MS_PER_SAMPLE 100 /* CPU Frequency */ #define MHZ #define CPU_FREQ 2660 MHZ /***** The code **************************************************************/ typedef struct settings_st { char *outfile; struct timespec poll_sleep; unsigned long new_data_thresh; unsigned long ms_per_sample; double cpu_freq; } settings_t; settings_t opts; int interrupted = 0; /* gets set if we get a SIGHUP */ int rec_count = 0; int wakeups = 0; time_t start_time; int dom0_flips = 0; _new_qos_data *new_qos; _new_qos_data **cpu_qos_data; // array of currently running domains, indexed by cpu int *running = NULL; // number of cpu's on this platform int NCPU = 0; void init_current(int ncpu) { running = calloc(ncpu, sizeof(int)); NCPU = ncpu; printf("Initialized with %d %s\n", ncpu, (ncpu == 1) ? "cpu" : "cpu's"); } int is_current(int domain, int cpu) { // int i; // for (i=0; icycles, x->event, x->data[0]); } #endif /** * millis_to_timespec - convert a time in milliseconds to a struct timespec * @millis: time interval in milliseconds */ struct timespec millis_to_timespec(unsigned long millis) { struct timespec spec; spec.tv_sec = millis / 1000; spec.tv_nsec = (millis % 1000) * 1000; return spec; } typedef struct { int event_count; int event_id; char *text; } stat_map_t; stat_map_t stat_map[] = { { 0, 0, "Other" }, { 0, TRC_SCHED_DOM_ADD, "Add Domain" }, { 0, TRC_SCHED_DOM_REM, "Remove Domain" }, { 0, TRC_SCHED_SLEEP, "Sleep" }, { 0, TRC_SCHED_WAKE, "Wake" }, { 0, TRC_SCHED_BLOCK, "Block" }, { 0, TRC_SCHED_SWITCH, "Switch" }, { 0, TRC_SCHED_S_TIMER_FN, "Timer Func"}, { 0, TRC_SCHED_SWITCH_INFPREV, "Switch Prev" }, { 0, TRC_SCHED_SWITCH_INFNEXT, "Switch Next" }, { 0, TRC_MEM_PAGE_GRANT_MAP, "Page Map" }, { 0, TRC_MEM_PAGE_GRANT_UNMAP, "Page Unmap" }, { 0, TRC_MEM_PAGE_GRANT_TRANSFER, "Page Transfer" }, { 0, 0, 0 } }; void check_gotten_sum(void) { #if 0 uint64_t sum, ns; extern uint64_t total_ns_gotten(uint64_t*); double percent; int i; for (i=0; i ns_gotten = %7.3f%%\n", percent); } #endif } void dump_stats(void) { stat_map_t *smt = stat_map; time_t end_time, run_time; time(&end_time); run_time = end_time - start_time; printf("Event counts:\n"); while (smt->text != NULL) { printf("%08d\t%s\n", smt->event_count, smt->text); smt++; } printf("processed %d total records in %d seconds (%ld per second)\n", rec_count, (int)run_time, rec_count/run_time); printf("woke up %d times in %d seconds (%ld per second)\n", wakeups, (int) run_time, wakeups/run_time); check_gotten_sum(); } void log_event(int event_id) { stat_map_t *smt = stat_map; // printf("event_id = 0x%x\n", event_id); while (smt->text != NULL) { if (smt->event_id == event_id) { smt->event_count++; return; } smt++; } if (smt->text == NULL) stat_map[0].event_count++; // other } #define EVTCHN_DEV_NAME "/dev/xen/evtchn" #define EVTCHN_DEV_MAJOR 10 #define EVTCHN_DEV_MINOR 201 int virq_port; int eventchn_fd = -1; /* Returns the event channel handle. */ /* Stolen from xenstore code */ int eventchn_init(void) { struct stat st; struct ioctl_evtchn_bind_virq bind; int rc; // to revert to old way: if (0) return -1; /* Make sure any existing device file links to correct device. */ if ((lstat(EVTCHN_DEV_NAME, &st) != 0) || !S_ISCHR(st.st_mode) || (st.st_rdev != makedev(EVTCHN_DEV_MAJOR, EVTCHN_DEV_MINOR))) (void)unlink(EVTCHN_DEV_NAME); reopen: eventchn_fd = open(EVTCHN_DEV_NAME, O_NONBLOCK|O_RDWR); if (eventchn_fd == -1) { if ((errno == ENOENT) && ((mkdir("/dev/xen", 0755) == 0) || (errno == EEXIST)) && (mknod(EVTCHN_DEV_NAME, S_IFCHR|0600, makedev(EVTCHN_DEV_MAJOR, EVTCHN_DEV_MINOR)) == 0)) goto reopen; return -errno; } if (eventchn_fd < 0) perror("Failed to open evtchn device"); bind.virq = VIRQ_TBUF; rc = ioctl(eventchn_fd, IOCTL_EVTCHN_BIND_VIRQ, &bind); if (rc == -1) perror("Failed to bind to domain exception virq port"); virq_port = rc; return eventchn_fd; } void wait_for_event(void) { int ret; fd_set inset; evtchn_port_t port; struct timeval tv; if (eventchn_fd < 0) { nanosleep(&opts.poll_sleep, NULL); return; } FD_ZERO(&inset); FD_SET(eventchn_fd, &inset); tv.tv_sec = 1; tv.tv_usec = 0; // tv = millis_to_timespec(&opts.poll_sleep); ret = select(eventchn_fd+1, &inset, NULL, NULL, &tv); if ( (ret == 1) && FD_ISSET(eventchn_fd, &inset)) { if (read(eventchn_fd, &port, sizeof(port)) != sizeof(port)) perror("Failed to read from event fd"); // if (port == virq_port) // printf("got the event I was looking for\r\n"); if (write(eventchn_fd, &port, sizeof(port)) != sizeof(port)) perror("Failed to write to event fd"); } } static void get_tbufs(unsigned long *mfn, unsigned long *size) { int xc_handle = xc_interface_open(); int ret; if ( xc_handle < 0 ) { exit(EXIT_FAILURE); } ret = xc_tbuf_enable(xc_handle, DEFAULT_TBUF_SIZE, mfn, size); if ( ret != 0 ) { perror("Couldn't enable trace buffers"); exit(1); } xc_interface_close(xc_handle); } void disable_t
--- a/Makefile
+++ b/Makefile
@@ -42,8 +42,8 @@ PLATS= aix ansi bsd freebsd generic linu
 
 # What to install.
 TO_BIN= lua luac
-TO_INC= lua.h luaconf.h lualib.h lauxlib.h ../etc/lua.hpp
-TO_LIB= liblua.a
+TO_INC= lua.h luaconf.h lualib.h lauxlib.h ../etc/lua.hpp lnum_config.h
+TO_LIB= liblua.a liblua.so.$R
 TO_MAN= lua.1 luac.1
 
 # Lua version and release.
@@ -63,6 +63,7 @@ install: dummy
 	cd src && $(INSTALL_EXEC) $(TO_BIN) $(INSTALL_BIN)
 	cd src && $(INSTALL_DATA) $(TO_INC) $(INSTALL_INC)
 	cd src && $(INSTALL_DATA) $(TO_LIB) $(INSTALL_LIB)
+	ln -s liblua.so.$R $(INSTALL_LIB)/liblua.so
 	cd doc && $(INSTALL_DATA) $(TO_MAN) $(INSTALL_MAN)
 
 ranlib:
--- a/src/ldo.h
+++ b/src/ldo.h
@@ -46,7 +46,7 @@ LUAI_FUNC int luaD_pcall (lua_State *L, 
 LUAI_FUNC int luaD_poscall (lua_State *L, StkId firstResult);
 LUAI_FUNC void luaD_reallocCI (lua_State *L, int newsize);
 LUAI_FUNC void luaD_reallocstack (lua_State *L, int newsize);
-LUAI_FUNC void luaD_growstack (lua_State *L, int n);
+LUA_API void luaD_growstack (lua_State *L, int n);
 
 LUAI_FUNC void luaD_throw (lua_State *L, int errcode);
 LUAI_FUNC int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud);
--- a/src/lfunc.h
+++ b/src/lfunc.h
@@ -18,7 +18,7 @@
                          cast(int, sizeof(TValue *)*((n)-1)))
 
 
-LUAI_FUNC Proto *luaF_newproto (lua_State *L);
+LUA_API Proto *luaF_newproto (lua_State *L);
 LUAI_FUNC Closure *luaF_newCclosure (lua_State *L, int nelems, Table *e);
 LUAI_FUNC Closure *luaF_newLclosure (lua_State *L, int nelems, Table *e);
 LUAI_FUNC UpVal *luaF_newupval (lua_State *L);
--- a/src/lmem.h
+++ b/src/lmem.h
@@ -38,9 +38,9 @@
    ((v)=cast(t *, luaM_reallocv(L, v, oldn, n, sizeof(t))))
 
 
-LUAI_FUNC void *luaM_realloc_ (lua_State *L, void *block, size_t oldsize,
+LUA_API void *luaM_realloc_ (lua_State *L, void *block, size_t oldsize,
                                                           size_t size);
-LUAI_FUNC void *luaM_toobig (lua_State *L);
+LUA_API void *luaM_toobig (lua_State *L);
 LUAI_FUNC void *luaM_growaux_ (lua_State *L, void *block, int *size,
                                size_t size_elem, int limit,
                                const char *errormsg);
--- a/src/lstring.h
+++ b/src/lstring.h
@@ -25,7 +25,7 @@
 
 LUAI_FUNC void luaS_resize (lua_State *L, int newsize);
 LUAI_FUNC Udata *luaS_newudata (lua_State *L, size_t s, Table *e);
-LUAI_FUNC TString *luaS_newlstr (lua_State *L, const char *str, size_t l);
+LUA_API TString *luaS_newlstr (lua_State *L, const char *str, size_t l);
 
 
 #endif
--- a/src/lundump.h
+++ b/src/lundump.h
@@ -17,7 +17,7 @@ LUAI_FUNC Proto* luaU_undump (lua_State*
 LUAI_FUNC void luaU_header (char* h);
 
 /* dump one chunk; from ldump.c */
-LUAI_FUNC int luaU_dump (lua_State* L, const Proto* f, lua_Writer w, void* data, int strip);
+LUA_API int luaU_dump (lua_State* L, const Proto* f, lua_Writer w, void* data, int strip);
 
 #ifdef luac_c
 /* print one chunk; from print.c */
--- a/src/Makefile
+++ b/src/Makefile
@@ -23,6 +23,7 @@ MYLIBS=
 PLATS= aix ansi bsd freebsd generic linux macosx mingw posix solaris
 
 LUA_A=	liblua.a
+LUA_SO= liblua.so
 CORE_O=	lapi.o lcode.o ldebug.o ldo.o ldump.o lfunc.o lgc.o llex.o lmem.o \
 	lobject.o lopcodes.o lparser.o lstate.o lstring.o ltable.o ltm.o  \
 	lundump.o lvm.o lzio.o lnum.o
@@ -33,11 +34,12 @@ LUA_T=	lua
 LUA_O=	lua.o
 
 LUAC_T=	luac
-LUAC_O=	luac.o print.o
+LUAC_O=	luac.o print.o lopcodes.o
 
 ALL_O= $(CORE_O) $(LIB_O) $(LUA_O) $(LUAC_O)
-ALL_T= $(LUA_A) $(LUA_T) $(LUAC_T)
+ALL_T= $(LUA_A) $(LUA_SO) $(LUA_T) $(LUAC_T)
 ALL_A= $(LUA_A)
+ALL_SO= $(LUA_SO)
 
 default: $(PLAT)
 
@@ -47,14 +49,23 @@ o:	$(ALL_O)
 
 a:	$(ALL_A)
 
+so:	$(ALL_SO)
+
 $(LUA_A): $(CORE_O) $(LIB_O)
 	$(AR) $@ $(CORE_O) $(LIB_O)	# DLL needs all object files
 	$(RANLIB) $@
 
-$(LUA_T): $(LUA_O) $(LUA_A)
-	$(CC) -o $@ $(MYLDFLAGS) $(LUA_O) $(LUA_A) $(LIBS)
+$(LUA_SO): $(CORE_O) $(LIB_O)
+	$(CC) -o $@.$(PKG_VERSION) -shared -Wl,-soname="$@.$(PKG_VERSION)" $?
+	ln -fs $@.$(PKG_VERSION) $@
+
+$(LUA_T): $(LUA_O) $(LUA_SO)
+	$(CC) -o $@ -L. -llua $(MYLDFLAGS) $(LUA_O) $(LIBS)
+
+$(LUAC_T): $(LUAC_O) $(LUA_SO)
+	$(CC) -o $@ -L. -llua $(MYLDFLAGS) $(LUAC_O) $(LIBS)
 
-$(LUAC_T): $(LUAC_O) $(LUA_A)
+$(LUAC_T)-host: $(LUAC_O) $(LUA_A)
 	$(CC) -o $@ $(MYLDFLAGS) $(LUAC_O) $(LUA_A) $(LIBS)
 
 clean:
@@ -96,7 +107,7 @@ generic:
 	$(MAKE) all MYCFLAGS=
 
 linux:
-	$(MAKE) all MYCFLAGS=-DLUA_USE_LINUX MYLIBS="-Wl,-E -ldl -lreadline -lhistory -lncurses"
+	$(MAKE) all MYCFLAGS+=-DLUA_USE_LINUX MYLIBS="-Wl,-E -ldl -lreadline -lhistory -lncurses"
 
 macosx:
 	$(MAKE) all MYCFLAGS=-DLUA_USE_LINUX MYLIBS="-lreadline"
idx++) { new_qos->qdata[new].ns_gotten[didx] = 0; new_qos->qdata[new].ns_allocated[didx] = 0; new_qos->qdata[new].ns_waiting[didx] = 0; new_qos->qdata[new].ns_blocked[didx] = 0; new_qos->qdata[new].switchin_count[didx] = 0; new_qos->qdata[new].io_count[didx] = 0; } new_qos->qdata[new].ns_passed = 0; new_qos->qdata[new].lost_records = 0; new_qos->qdata[new].flip_free_periods = 0; new_qos->qdata[new].timestamp = now; } void qos_update_thread(int cpu, int domid, uint64_t now) { int n, id; uint64_t last_update_time, start; int64_t time_since_update, run_time = 0; id = ID(domid); n = new_qos->next_datapoint; last_update_time = new_qos->domain_info[id].last_update_time; time_since_update = now - last_update_time; if (time_since_update < 0) { // what happened here? either a timestamp wraparound, or more likely, // a slight inconsistency among timestamps from various cpu's if (-time_since_update < billion) { // fairly small difference, let's just adjust 'now' to be a little // beyond last_update_time time_since_update = -time_since_update; } else if ( ((~0ULL - last_update_time) < billion) && (now < billion) ) { // difference is huge, must be a wraparound // last_update time should be "near" ~0ULL, // and now should be "near" 0 time_since_update = now + (~0ULL - last_update_time); printf("time wraparound\n"); } else { // none of the above, may be an out of order record // no good solution, just ignore and update again later return; } } new_qos->domain_info[id].last_update_time = now; if (new_qos->domain_info[id].runnable_at_last_update && is_current(domid, cpu)) { start = new_qos->domain_info[id].start_time; if (start > now) { // wrapped around run_time = now + (~0ULL - start); // this could happen if there is nothing going on within a cpu; // in this case the idle domain would run forever // printf("warning: start > now\n"); } else run_time = now - start; // if (run_time < 0) // should not happen // printf("warning: run_time < 0; start = %lld now= %lld\n", start, now); new_qos->domain_info[id].ns_oncpu_since_boot += run_time; new_qos->domain_info[id].start_time = now; new_qos->domain_info[id].ns_since_boot += time_since_update; new_qos->qdata[n].ns_gotten[id] += run_time; // if (domid == 0 && cpu == 1) // printf("adding run time for dom0 on cpu1\r\n"); } new_qos->domain_info[id].runnable_at_last_update = domain_runnable(domid); update_blocked_time(domid, now); // how much time passed since this datapoint was updated? if (now >= new_qos->qdata[n].timestamp) { // all is right with the world, time is increasing new_qos->qdata[n].ns_passed += (now - new_qos->qdata[n].timestamp); } else { // time wrapped around //new_qos->qdata[n].ns_passed += (now + (~0LL - new_qos->qdata[n].timestamp)); // printf("why timewrap?\r\n"); } new_qos->qdata[n].timestamp = now; } // called by dump routines to update all structures void qos_update_all(uint64_t now, int cpu) { int i; for (i=0; idomain_info[i].in_use) qos_update_thread(cpu, i, now); } void qos_update_thread_stats(int cpu, int domid, uint64_t now) { if (new_qos->qdata[new_qos->next_datapoint].ns_passed > (million*opts.ms_per_sample)) { qos_update_all(now, cpu); advance_next_datapoint(now); return; } qos_update_thread(cpu, domid, now); } void qos_init_domain(int cpu, int domid, uint64_t now) { int i, id; id = ID(domid); if (new_qos->domain_info[id].in_use) return; memset(&new_qos->domain_info[id], 0, sizeof(_domain_info)); new_qos->domain_info[id].last_update_time = now; // runnable_start_time[id] = 0; new_qos->domain_info[id].runnable_start_time = 0; // invalidate new_qos->domain_info[id].in_use = 1; new_qos->domain_info[id].blocked_start_time = 0; new_qos->domain_info[id].id = id; if (domid == IDLE_DOMAIN_ID) sprintf(new_qos->domain_info[id].name, "Idle Task%d", cpu); else sprintf(new_qos->domain_info[id].name, "Domain#%d", domid); for (i=0; iqdata[i].ns_gotten[id] = 0; new_qos->qdata[i].ns_allocated[id] = 0; new_qos->qdata[i].ns_waiting[id] = 0; new_qos->qdata[i].ns_blocked[id] = 0; new_qos->qdata[i].switchin_count[id] = 0; new_qos->qdata[i].io_count[id] = 0; } } // called when a new thread gets the cpu void qos_switch_in(int cpu, int domid, uint64_t now, unsigned long ns_alloc, unsigned long ns_waited) { int id = ID(domid); new_qos->domain_info[id].runnable = 1; update_blocked_time(domid, now); new_qos->domain_info[id].blocked_start_time = 0; // invalidate new_qos->domain_info[id].runnable_start_time = 0; // invalidate //runnable_start_time[id] = 0; new_qos->domain_info[id].start_time = now; new_qos->qdata[new_qos->next_datapoint].switchin_count[id]++; new_qos->qdata[new_qos->next_datapoint].ns_allocated[id] += ns_alloc; new_qos->qdata[new_qos->next_datapoint].ns_waiting[id] += ns_waited; qos_update_thread_stats(cpu, domid, now); set_current(cpu, id); // count up page flips for dom0 execution if (id == 0) dom0_flips = 0; } // called when the current thread is taken off the cpu void qos_switch_out(int cpu, int domid, uint64_t now, unsigned long gotten) { int id = ID(domid); int n; if (!is_current(id, cpu)) { // printf("switching out domain %d but it is not current. gotten=%ld\r\n", id, gotten); } if (gotten == 0) { printf("gotten==0 in qos_switchout(domid=%d)\n", domid); } if (gotten < 100) { printf("gotten<100ns in qos_switchout(domid=%d)\n", domid); } n = new_qos->next_datapoint; #if 0 new_qos->qdata[n].ns_gotten[id] += gotten; if (gotten > new_qos->qdata[n].ns_passed) printf("inconsistency #257, diff = %lld\n", gotten - new_qos->qdata[n].ns_passed ); #endif new_qos->domain_info[id].ns_oncpu_since_boot += gotten; new_qos->domain_info[id].runnable_start_time = now; // runnable_start_time[id] = now; qos_update_thread_stats(cpu, id, now); // process dom0 page flips if (id == 0) if (dom0_flips == 0) new_qos->qdata[n].flip_free_periods++; } // called when domain is put to sleep, may also be called // when thread is already asleep void qos_state_sleeping(int cpu, int domid, uint64_t now) { int id = ID(domid); if (!domain_runnable(id)) // double call? return; new_qos->domain_info[id].runnable = 0; new_qos->domain_info[id].blocked_start_time = now; new_qos->domain_info[id].runnable_start_time = 0; // invalidate // runnable_start_time[id] = 0; // invalidate qos_update_thread_stats(cpu, domid, now); } void qos_kill_thread(int domid) { new_qos->domain_info[ID(domid)].in_use = 0; } // called when thread becomes runnable, may also be called // when thread is already runnable void qos_state_runnable(int cpu, int domid, uint64_t now) { int id = ID(domid); qos_update_thread_stats(cpu, domid, now); if (domain_runnable(id)) // double call? return; new_qos->domain_info[id].runnable = 1; update_blocked_time(domid, now); new_qos->domain_info[id].blocked_start_time = 0; /* invalidate */ new_qos->domain_info[id].runnable_start_time = now; // runnable_start_time[id] = now; } void qos_count_packets(domid_t domid, uint64_t now) { int i, id = ID(domid); _new_qos_data *cpu_data; for (i=0; idomain_info[id].in_use) { cpu_data->qdata[cpu_data->next_datapoint].io_count[id]++; } } new_qos->qdata[new_qos->next_datapoint].io_count[0]++; dom0_flips++; } int domain_ok(int cpu, int domid, uint64_t now) { if (domid == IDLE_DOMAIN_ID) domid = NDOMAINS-1; if (domid < 0 || domid >= NDOMAINS) { printf("bad domain id: %d\r\n", domid); return 0; } if (new_qos->domain_info[domid].in_use == 0) qos_init_domain(cpu, domid, now); return 1; } void process_record(int cpu, struct t_rec *r) { uint64_t now; new_qos = cpu_qos_data[cpu]; rec_count++; now = ((double)r->cycles) / (opts.cpu_freq / 1000.0); log_event(r->event); switch (r->event) { case TRC_SCHED_SWITCH_INFPREV: // domain data[0] just switched out and received data[1] ns of cpu time if (domain_ok(cpu, r->data[0], now)) qos_switch_out(cpu, r->data[0], now, r->data[1]); // printf("ns_gotten %ld\n", r->data[1]); break; case TRC_SCHED_SWITCH_INFNEXT: // domain data[0] just switched in and // waited data[1] ns, and was allocated data[2] ns of cpu time if (domain_ok(cpu, r->data[0], now)) qos_switch_in(cpu, r->data[0], now, r->data[2], r->data[1]); break; case TRC_SCHED_DOM_ADD: if (domain_ok(cpu, r->data[0], now)) qos_init_domain(cpu, r->data[0], now); break; case TRC_SCHED_DOM_REM: if (domain_ok(cpu, r->data[0], now)) qos_kill_thread(r->data[0]); break; case TRC_SCHED_SLEEP: if (domain_ok(cpu, r->data[0], now)) qos_state_sleeping(cpu, r->data[0], now); break; case TRC_SCHED_WAKE: if (domain_ok(cpu, r->data[0], now)) qos_state_runnable(cpu, r->data[0], now); break; case TRC_SCHED_BLOCK: if (domain_ok(cpu, r->data[0], now)) qos_state_sleeping(cpu, r->data[0], now); break; case TRC_MEM_PAGE_GRANT_TRANSFER: if (domain_ok(cpu, r->data[0], now)) qos_count_packets(r->data[0], now); break; default: break; } new_qos = NULL; }