From 0410ae29c0dde2d148e3b909bc44b90cfb796dfd Mon Sep 17 00:00:00 2001 From: Cole Robinson Date: Jun 15 2014 21:58:34 +0000 Subject: Don't use libtool on dtrace, fixes rawhide build (bz #1106968) --- diff --git a/0107-trace-add-pid-field-to-simpletrace-record.patch b/0107-trace-add-pid-field-to-simpletrace-record.patch new file mode 100644 index 0000000..e8dc6f6 --- /dev/null +++ b/0107-trace-add-pid-field-to-simpletrace-record.patch @@ -0,0 +1,70 @@ +From 32f3e4afa3c9e67c6448b2f3e3aefc4d7cf5a0d3 Mon Sep 17 00:00:00 2001 +From: Stefan Hajnoczi +Date: Wed, 7 May 2014 19:24:10 +0200 +Subject: [PATCH] trace: add pid field to simpletrace record + +It is useful to know the QEMU process ID when working with traces from +multiple VMs. Although the trace filename may contain the pid, tools +that aggregate traces or even trace globally need somewhere to record +the pid. + +There is a reserved field in the trace event header struct that we can +use. + +It is not necessary to bump the simpletrace file format version number +because it has already been incremented for the QEMU 2.1 release cycle +in commit "trace: [simple] Bump up log version number". + +Signed-off-by: Stefan Hajnoczi +(cherry picked from commit 26896cbf353e3017f76da8193074839b6e875250) +--- + trace/simple.c | 8 ++++++-- + 1 file changed, 6 insertions(+), 2 deletions(-) + +diff --git a/trace/simple.c b/trace/simple.c +index aaa010e..1584bf7 100644 +--- a/trace/simple.c ++++ b/trace/simple.c +@@ -75,6 +75,7 @@ uint8_t trace_buf[TRACE_BUF_LEN]; + static volatile gint trace_idx; + static unsigned int writeout_idx; + static volatile gint dropped_events; ++static uint32_t trace_pid; + static FILE *trace_fp; + static char *trace_file_name; + +@@ -83,7 +84,7 @@ typedef struct { + uint64_t event; /* TraceEventID */ + uint64_t timestamp_ns; + uint32_t length; /* in bytes */ +- uint32_t reserved; /* unused */ ++ uint32_t pid; + uint64_t arguments[]; + } TraceRecord; + +@@ -190,7 +191,7 @@ static gpointer writeout_thread(gpointer opaque) + dropped.rec.event = DROPPED_EVENT_ID, + dropped.rec.timestamp_ns = get_clock(); + dropped.rec.length = sizeof(TraceRecord) + sizeof(uint64_t), +- dropped.rec.reserved = 0; ++ dropped.rec.pid = trace_pid; + do { + dropped_count = g_atomic_int_get(&dropped_events); + } while (!g_atomic_int_compare_and_exchange(&dropped_events, +@@ -249,6 +250,7 @@ int trace_record_start(TraceBufferRecord *rec, TraceEventID event, size_t datasi + rec_off = write_to_buffer(rec_off, &event_u64, sizeof(event_u64)); + rec_off = write_to_buffer(rec_off, ×tamp_ns, sizeof(timestamp_ns)); + rec_off = write_to_buffer(rec_off, &rec_len, sizeof(rec_len)); ++ rec_off = write_to_buffer(rec_off, &trace_pid, sizeof(trace_pid)); + + rec->tbuf_idx = idx; + rec->rec_off = (idx + sizeof(TraceRecord)) % TRACE_BUF_LEN; +@@ -414,6 +416,8 @@ bool trace_backend_init(const char *events, const char *file) + { + GThread *thread; + ++ trace_pid = getpid(); ++ + #if !GLIB_CHECK_VERSION(2, 31, 0) + trace_available_cond = g_cond_new(); + trace_empty_cond = g_cond_new(); diff --git a/0108-simpletrace-add-support-for-trace-record-pid-field.patch b/0108-simpletrace-add-support-for-trace-record-pid-field.patch new file mode 100644 index 0000000..6a270fa --- /dev/null +++ b/0108-simpletrace-add-support-for-trace-record-pid-field.patch @@ -0,0 +1,100 @@ +From 012d97190b01b0726c47aa46d723b81fa4d193d4 Mon Sep 17 00:00:00 2001 +From: Stefan Hajnoczi +Date: Wed, 7 May 2014 19:24:11 +0200 +Subject: [PATCH] simpletrace: add support for trace record pid field + +Extract the pid field from the trace record and print it. + +Change the trace record tuple from: + (event_num, timestamp, arg1, ..., arg6) +to: + (event_num, timestamp, pid, arg1, ..., arg6) + +Trace event methods now support 3 prototypes: +1. (arg1, arg2, arg3) +2. (timestamp, arg1, arg2, arg3) +3. (timestamp, pid, arg1, arg2, arg3) + +Existing script continue to work without changes, they only know about +prototypes 1 and 2. + +Signed-off-by: Stefan Hajnoczi +(cherry picked from commit 80ff35cd3ff451e8f200413ddf27816058630c1f) +--- + scripts/simpletrace.py | 26 +++++++++++++++----------- + 1 file changed, 15 insertions(+), 11 deletions(-) + +diff --git a/scripts/simpletrace.py b/scripts/simpletrace.py +index 8bbcb42..e1b97d4 100755 +--- a/scripts/simpletrace.py ++++ b/scripts/simpletrace.py +@@ -31,10 +31,10 @@ def read_header(fobj, hfmt): + return struct.unpack(hfmt, hdr) + + def get_record(edict, rechdr, fobj): +- """Deserialize a trace record from a file into a tuple (event_num, timestamp, arg1, ..., arg6).""" ++ """Deserialize a trace record from a file into a tuple (event_num, timestamp, pid, arg1, ..., arg6).""" + if rechdr is None: + return None +- rec = (rechdr[0], rechdr[1]) ++ rec = (rechdr[0], rechdr[1], rechdr[3]) + if rechdr[0] != dropped_event_id: + event_id = rechdr[0] + event = edict[event_id] +@@ -54,12 +54,12 @@ def get_record(edict, rechdr, fobj): + + + def read_record(edict, fobj): +- """Deserialize a trace record from a file into a tuple (event_num, timestamp, arg1, ..., arg6).""" ++ """Deserialize a trace record from a file into a tuple (event_num, timestamp, pid, arg1, ..., arg6).""" + rechdr = read_header(fobj, rec_header_fmt) + return get_record(edict, rechdr, fobj) # return tuple of record elements + + def read_trace_file(edict, fobj): +- """Deserialize trace records from a file, yielding record tuples (event_num, timestamp, arg1, ..., arg6).""" ++ """Deserialize trace records from a file, yielding record tuples (event_num, timestamp, pid, arg1, ..., arg6).""" + header = read_header(fobj, log_header_fmt) + if header is None or \ + header[0] != header_event_id or \ +@@ -131,10 +131,13 @@ def process(events, log, analyzer): + fn_argcount = len(inspect.getargspec(fn)[0]) - 1 + if fn_argcount == event_argcount + 1: + # Include timestamp as first argument +- return lambda _, rec: fn(*rec[1:2 + event_argcount]) ++ return lambda _, rec: fn(*((rec[1:2],) + rec[3:3 + event_argcount])) ++ elif fn_argcount == event_argcount + 2: ++ # Include timestamp and pid ++ return lambda _, rec: fn(*rec[1:3 + event_argcount]) + else: +- # Just arguments, no timestamp +- return lambda _, rec: fn(*rec[2:2 + event_argcount]) ++ # Just arguments, no timestamp or pid ++ return lambda _, rec: fn(*rec[3:3 + event_argcount]) + + analyzer.begin() + fn_cache = {} +@@ -166,19 +169,20 @@ if __name__ == '__main__': + self.last_timestamp = None + + def catchall(self, event, rec): +- i = 1 + timestamp = rec[1] + if self.last_timestamp is None: + self.last_timestamp = timestamp + delta_ns = timestamp - self.last_timestamp + self.last_timestamp = timestamp + +- fields = [event.name, '%0.3f' % (delta_ns / 1000.0)] ++ fields = [event.name, '%0.3f' % (delta_ns / 1000.0), ++ 'pid=%d' % rec[2]] ++ i = 3 + for type, name in event.args: + if is_string(type): +- fields.append('%s=%s' % (name, rec[i + 1])) ++ fields.append('%s=%s' % (name, rec[i])) + else: +- fields.append('%s=0x%x' % (name, rec[i + 1])) ++ fields.append('%s=0x%x' % (name, rec[i])) + i += 1 + print ' '.join(fields) + diff --git a/0109-trace-Replace-error-with-warning-if-event-is-not-def.patch b/0109-trace-Replace-error-with-warning-if-event-is-not-def.patch new file mode 100644 index 0000000..273bf8c --- /dev/null +++ b/0109-trace-Replace-error-with-warning-if-event-is-not-def.patch @@ -0,0 +1,46 @@ +From 2e6870993d226dd8af3e2db502e8e183ee63d66a Mon Sep 17 00:00:00 2001 +From: Alexey Kardashevskiy +Date: Wed, 21 May 2014 18:16:01 +1000 +Subject: [PATCH] trace: Replace error with warning if event is not defined + +At the moment QEMU exits if trace point is not defined which makes +a developer life harder if he has to switch between branches with +different traces implemented. + +This replaces error+exit wit WARNING if the tracepoint does not exist or +not traceable. + +Signed-off-by: Alexey Kardashevskiy +Signed-off-by: Stefan Hajnoczi +(cherry picked from commit 82432638ebeedda8a2e18838b6fbef4b14a94f31) +--- + trace/control.c | 14 +++++++------- + 1 file changed, 7 insertions(+), 7 deletions(-) + +diff --git a/trace/control.c b/trace/control.c +index 49f61e1..4aa02cf 100644 +--- a/trace/control.c ++++ b/trace/control.c +@@ -112,15 +112,15 @@ void trace_backend_init_events(const char *fname) + TraceEvent *ev = trace_event_name(line_ptr); + if (ev == NULL) { + fprintf(stderr, +- "error: trace event '%s' does not exist\n", line_ptr); +- exit(1); +- } +- if (!trace_event_get_state_static(ev)) { ++ "WARNING: trace event '%s' does not exist\n", ++ line_ptr); ++ } else if (!trace_event_get_state_static(ev)) { + fprintf(stderr, +- "error: trace event '%s' is not traceable\n", line_ptr); +- exit(1); ++ "WARNING: trace event '%s' is not traceable\n", ++ line_ptr); ++ } else { ++ trace_event_set_state_dynamic(ev, enable); + } +- trace_event_set_state_dynamic(ev, enable); + } + } + } diff --git a/0110-do-not-call-g_thread_init-for-glib-2.31.patch b/0110-do-not-call-g_thread_init-for-glib-2.31.patch new file mode 100644 index 0000000..30675c4 --- /dev/null +++ b/0110-do-not-call-g_thread_init-for-glib-2.31.patch @@ -0,0 +1,78 @@ +From 6b1371a666af982f2d6c0b7dba98c425ea56d3dd Mon Sep 17 00:00:00 2001 +From: Michael Tokarev +Date: Fri, 2 May 2014 18:35:55 +0400 +Subject: [PATCH] do not call g_thread_init() for glib >= 2.31 + +glib >= 2.31 always enables thread support and g_thread_supported() +is #defined to 1, there's no need to call g_thread_init() anymore, +and it definitely does not need to report error which never happens. +Keep code for old < 2.31 glibc anyway for now, just #ifdef it +differently. + +Signed-off-by: Michael Tokarev +Reviewed-by: Stefan Hajnoczi +Cc: qemu-trivial@nongnu.org +(cherry picked from commit f33cc84dd4af7776309d118412df008ec4108a57) +--- + coroutine-gthread.c | 7 ++----- + util/osdep.c | 21 +++++++++------------ + 2 files changed, 11 insertions(+), 17 deletions(-) + +diff --git a/coroutine-gthread.c b/coroutine-gthread.c +index d3e5b99..a61efe0 100644 +--- a/coroutine-gthread.c ++++ b/coroutine-gthread.c +@@ -115,14 +115,11 @@ static inline GThread *create_thread(GThreadFunc func, gpointer data) + + static void __attribute__((constructor)) coroutine_init(void) + { +- if (!g_thread_supported()) { + #if !GLIB_CHECK_VERSION(2, 31, 0) ++ if (!g_thread_supported()) { + g_thread_init(NULL); +-#else +- fprintf(stderr, "glib threading failed to initialize.\n"); +- exit(1); +-#endif + } ++#endif + + init_coroutine_cond(); + } +diff --git a/util/osdep.c b/util/osdep.c +index a9029f8..b2bd154 100644 +--- a/util/osdep.c ++++ b/util/osdep.c +@@ -436,23 +436,20 @@ int socket_init(void) + return 0; + } + +-/* Ensure that glib is running in multi-threaded mode */ ++#if !GLIB_CHECK_VERSION(2, 31, 0) ++/* Ensure that glib is running in multi-threaded mode ++ * Old versions of glib require explicit initialization. Failure to do ++ * this results in the single-threaded code paths being taken inside ++ * glib. For example, the g_slice allocator will not be thread-safe ++ * and cause crashes. ++ */ + static void __attribute__((constructor)) thread_init(void) + { + if (!g_thread_supported()) { +-#if !GLIB_CHECK_VERSION(2, 31, 0) +- /* Old versions of glib require explicit initialization. Failure to do +- * this results in the single-threaded code paths being taken inside +- * glib. For example, the g_slice allocator will not be thread-safe +- * and cause crashes. +- */ +- g_thread_init(NULL); +-#else +- fprintf(stderr, "glib threading failed to initialize.\n"); +- exit(1); +-#endif ++ g_thread_init(NULL); + } + } ++#endif + + #ifndef CONFIG_IOVEC + /* helper function for iov_send_recv() */ diff --git a/0111-glib-move-g_poll-replacement-into-glib-compat.h.patch b/0111-glib-move-g_poll-replacement-into-glib-compat.h.patch new file mode 100644 index 0000000..70117f9 --- /dev/null +++ b/0111-glib-move-g_poll-replacement-into-glib-compat.h.patch @@ -0,0 +1,62 @@ +From 6c1369c499e74fccbbfb97b3ec3e5da59d382031 Mon Sep 17 00:00:00 2001 +From: Stefan Hajnoczi +Date: Fri, 2 May 2014 18:35:56 +0400 +Subject: [PATCH] glib: move g_poll() replacement into glib-compat.h + +We have a dedicated header file for wrappers to smooth over glib version +differences. Move the g_poll() definition into glib-compat.h for +consistency. + +Signed-off-by: Stefan Hajnoczi +Signed-off-by: Michael Tokarev +Cc: qemu-trivial@nongnu.org +(cherry picked from commit f95c967a7950797109d2a96fcfa2e3a2899f2c99) +--- + include/glib-compat.h | 12 ++++++++++++ + include/qemu-common.h | 12 ------------ + 2 files changed, 12 insertions(+), 12 deletions(-) + +diff --git a/include/glib-compat.h b/include/glib-compat.h +index 8aa77af..8d25900 100644 +--- a/include/glib-compat.h ++++ b/include/glib-compat.h +@@ -24,4 +24,16 @@ static inline guint g_timeout_add_seconds(guint interval, GSourceFunc function, + } + #endif + ++#if !GLIB_CHECK_VERSION(2, 20, 0) ++/* ++ * Glib before 2.20.0 doesn't implement g_poll, so wrap it to compile properly ++ * on older systems. ++ */ ++static inline gint g_poll(GPollFD *fds, guint nfds, gint timeout) ++{ ++ GMainContext *ctx = g_main_context_default(); ++ return g_main_context_get_poll_func(ctx)(fds, nfds, timeout); ++} ++#endif ++ + #endif +diff --git a/include/qemu-common.h b/include/qemu-common.h +index a998e8d..3f3fd60 100644 +--- a/include/qemu-common.h ++++ b/include/qemu-common.h +@@ -124,18 +124,6 @@ int qemu_main(int argc, char **argv, char **envp); + void qemu_get_timedate(struct tm *tm, int offset); + int qemu_timedate_diff(struct tm *tm); + +-#if !GLIB_CHECK_VERSION(2, 20, 0) +-/* +- * Glib before 2.20.0 doesn't implement g_poll, so wrap it to compile properly +- * on older systems. +- */ +-static inline gint g_poll(GPollFD *fds, guint nfds, gint timeout) +-{ +- GMainContext *ctx = g_main_context_default(); +- return g_main_context_get_poll_func(ctx)(fds, nfds, timeout); +-} +-#endif +- + /** + * is_help_option: + * @s: string to test diff --git a/0112-glib-fix-g_poll-early-timeout-on-windows.patch b/0112-glib-fix-g_poll-early-timeout-on-windows.patch new file mode 100644 index 0000000..00bfd53 --- /dev/null +++ b/0112-glib-fix-g_poll-early-timeout-on-windows.patch @@ -0,0 +1,171 @@ +From 488f948b9f89a0dd90ed465f5d692230af2ecb05 Mon Sep 17 00:00:00 2001 +From: Sangho Park +Date: Thu, 8 May 2014 12:47:10 +0400 +Subject: [PATCH] glib: fix g_poll early timeout on windows + +g_poll has a problem on Windows when using +timeouts < 10ms, in glib/gpoll.c: + +/* If not, and we have a significant timeout, poll again with + * timeout then. Note that this will return indication for only + * one event, or only for messages. We ignore timeouts less than + * ten milliseconds as they are mostly pointless on Windows, the + * MsgWaitForMultipleObjectsEx() call will timeout right away + * anyway. + */ +if (retval == 0 && (timeout == INFINITE || timeout >= 10)) + retval = poll_rest (poll_msgs, handles, nhandles, fds, nfds, timeout); + +so whenever g_poll is called with timeout < 10ms it does +a quick poll instead of wait, this causes significant performance +degradation of QEMU, thus we should use WaitForMultipleObjectsEx +directly + +Signed-off-by: Stanislav Vorobiov +Signed-off-by: Stefan Hajnoczi +(cherry picked from commit 5a007547df76446ab891df93ebc55749716609bf) +--- + include/glib-compat.h | 9 +++- + util/oslib-win32.c | 112 ++++++++++++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 120 insertions(+), 1 deletion(-) + +diff --git a/include/glib-compat.h b/include/glib-compat.h +index 8d25900..1280fb2 100644 +--- a/include/glib-compat.h ++++ b/include/glib-compat.h +@@ -24,7 +24,14 @@ static inline guint g_timeout_add_seconds(guint interval, GSourceFunc function, + } + #endif + +-#if !GLIB_CHECK_VERSION(2, 20, 0) ++#ifdef _WIN32 ++/* ++ * g_poll has a problem on Windows when using ++ * timeouts < 10ms, so use wrapper. ++ */ ++#define g_poll(fds, nfds, timeout) g_poll_fixed(fds, nfds, timeout) ++gint g_poll_fixed(GPollFD *fds, guint nfds, gint timeout); ++#elif !GLIB_CHECK_VERSION(2, 20, 0) + /* + * Glib before 2.20.0 doesn't implement g_poll, so wrap it to compile properly + * on older systems. +diff --git a/util/oslib-win32.c b/util/oslib-win32.c +index 93f7d35..69552f7 100644 +--- a/util/oslib-win32.c ++++ b/util/oslib-win32.c +@@ -238,3 +238,115 @@ char *qemu_get_exec_dir(void) + { + return g_strdup(exec_dir); + } ++ ++/* ++ * g_poll has a problem on Windows when using ++ * timeouts < 10ms, in glib/gpoll.c: ++ * ++ * // If not, and we have a significant timeout, poll again with ++ * // timeout then. Note that this will return indication for only ++ * // one event, or only for messages. We ignore timeouts less than ++ * // ten milliseconds as they are mostly pointless on Windows, the ++ * // MsgWaitForMultipleObjectsEx() call will timeout right away ++ * // anyway. ++ * ++ * if (retval == 0 && (timeout == INFINITE || timeout >= 10)) ++ * retval = poll_rest (poll_msgs, handles, nhandles, fds, nfds, timeout); ++ * ++ * So whenever g_poll is called with timeout < 10ms it does ++ * a quick poll instead of wait, this causes significant performance ++ * degradation of QEMU, thus we should use WaitForMultipleObjectsEx ++ * directly ++ */ ++gint g_poll_fixed(GPollFD *fds, guint nfds, gint timeout) ++{ ++ guint i; ++ HANDLE handles[MAXIMUM_WAIT_OBJECTS]; ++ gint nhandles = 0; ++ int num_completed = 0; ++ ++ for (i = 0; i < nfds; i++) { ++ gint j; ++ ++ if (fds[i].fd <= 0) { ++ continue; ++ } ++ ++ /* don't add same handle several times ++ */ ++ for (j = 0; j < nhandles; j++) { ++ if (handles[j] == (HANDLE)fds[i].fd) { ++ break; ++ } ++ } ++ ++ if (j == nhandles) { ++ if (nhandles == MAXIMUM_WAIT_OBJECTS) { ++ fprintf(stderr, "Too many handles to wait for!\n"); ++ break; ++ } else { ++ handles[nhandles++] = (HANDLE)fds[i].fd; ++ } ++ } ++ } ++ ++ for (i = 0; i < nfds; ++i) { ++ fds[i].revents = 0; ++ } ++ ++ if (timeout == -1) { ++ timeout = INFINITE; ++ } ++ ++ if (nhandles == 0) { ++ if (timeout == INFINITE) { ++ return -1; ++ } else { ++ SleepEx(timeout, TRUE); ++ return 0; ++ } ++ } ++ ++ while (1) { ++ DWORD res; ++ gint j; ++ ++ res = WaitForMultipleObjectsEx(nhandles, handles, FALSE, ++ timeout, TRUE); ++ ++ if (res == WAIT_FAILED) { ++ for (i = 0; i < nfds; ++i) { ++ fds[i].revents = 0; ++ } ++ ++ return -1; ++ } else if ((res == WAIT_TIMEOUT) || (res == WAIT_IO_COMPLETION) || ++ ((int)res < (int)WAIT_OBJECT_0) || ++ (res >= (WAIT_OBJECT_0 + nhandles))) { ++ break; ++ } ++ ++ for (i = 0; i < nfds; ++i) { ++ if (handles[res - WAIT_OBJECT_0] == (HANDLE)fds[i].fd) { ++ fds[i].revents = fds[i].events; ++ } ++ } ++ ++ ++num_completed; ++ ++ if (nhandles <= 1) { ++ break; ++ } ++ ++ /* poll the rest of the handles ++ */ ++ for (j = res - WAIT_OBJECT_0 + 1; j < nhandles; j++) { ++ handles[j - 1] = handles[j]; ++ } ++ --nhandles; ++ ++ timeout = 0; ++ } ++ ++ return num_completed; ++} diff --git a/0113-glib-compat.h-add-new-thread-API-emulation-on-top-of.patch b/0113-glib-compat.h-add-new-thread-API-emulation-on-top-of.patch new file mode 100644 index 0000000..f79651f --- /dev/null +++ b/0113-glib-compat.h-add-new-thread-API-emulation-on-top-of.patch @@ -0,0 +1,350 @@ +From 57a1d211179279727d5afa21a7feba2d249d6867 Mon Sep 17 00:00:00 2001 +From: Michael Tokarev +Date: Thu, 8 May 2014 12:30:46 +0400 +Subject: [PATCH] glib-compat.h: add new thread API emulation on top of + pre-2.31 API + +Thread API changed in glib-2.31 significantly. Before that version, +conditionals and mutexes were only allocated dynamically, using +_new()/_free() interface. in 2.31 and up, they're allocated statically +as regular variables, and old interface is deprecated. + +(Note: glib docs says the new interface is available since version +2.32, but it was actually introduced in version 2.31). + +Create the new interface using old primitives, by providing non-opaque +definitions of the base types (GCond and GMutex) using GOnces. + +Replace #ifdeffery around GCond and GMutex in trace/simple.c and +coroutine-gthread.c too because it does not work anymore with the new +glib-compat.h. + +Signed-off-by: Michael Tokarev +Reviewed-by: Stefan Hajnoczi +[Use GOnce to support lazy initialization; introduce CompatGMutex + and CompatGCond. - Paolo] +Signed-off-by: Paolo Bonzini + +(cherry picked from commit 86946a2d835614050b90bc8e5c82982fe45deff2) +--- + coroutine-gthread.c | 29 ++++-------- + include/glib-compat.h | 119 ++++++++++++++++++++++++++++++++++++++++++++++++++ + trace/simple.c | 50 +++++---------------- + 3 files changed, 138 insertions(+), 60 deletions(-) + +diff --git a/coroutine-gthread.c b/coroutine-gthread.c +index a61efe0..6bd6d6b 100644 +--- a/coroutine-gthread.c ++++ b/coroutine-gthread.c +@@ -30,20 +30,14 @@ typedef struct { + CoroutineAction action; + } CoroutineGThread; + +-static GStaticMutex coroutine_lock = G_STATIC_MUTEX_INIT; ++static CompatGMutex coroutine_lock; ++static CompatGCond coroutine_cond; + + /* GLib 2.31 and beyond deprecated various parts of the thread API, + * but the new interfaces are not available in older GLib versions + * so we have to cope with both. + */ + #if GLIB_CHECK_VERSION(2, 31, 0) +-/* Default zero-initialisation is sufficient for 2.31+ GCond */ +-static GCond the_coroutine_cond; +-static GCond *coroutine_cond = &the_coroutine_cond; +-static inline void init_coroutine_cond(void) +-{ +-} +- + /* Awkwardly, the GPrivate API doesn't provide a way to update the + * GDestroyNotify handler for the coroutine key dynamically. So instead + * we track whether or not the CoroutineGThread should be freed on +@@ -84,11 +78,6 @@ static inline GThread *create_thread(GThreadFunc func, gpointer data) + #else + + /* Handle older GLib versions */ +-static GCond *coroutine_cond; +-static inline void init_coroutine_cond(void) +-{ +- coroutine_cond = g_cond_new(); +-} + + static GStaticPrivate coroutine_key = G_STATIC_PRIVATE_INIT; + +@@ -120,22 +109,20 @@ static void __attribute__((constructor)) coroutine_init(void) + g_thread_init(NULL); + } + #endif +- +- init_coroutine_cond(); + } + + static void coroutine_wait_runnable_locked(CoroutineGThread *co) + { + while (!co->runnable) { +- g_cond_wait(coroutine_cond, g_static_mutex_get_mutex(&coroutine_lock)); ++ g_cond_wait(&coroutine_cond, &coroutine_lock); + } + } + + static void coroutine_wait_runnable(CoroutineGThread *co) + { +- g_static_mutex_lock(&coroutine_lock); ++ g_mutex_lock(&coroutine_lock); + coroutine_wait_runnable_locked(co); +- g_static_mutex_unlock(&coroutine_lock); ++ g_mutex_unlock(&coroutine_lock); + } + + static gpointer coroutine_thread(gpointer opaque) +@@ -177,17 +164,17 @@ CoroutineAction qemu_coroutine_switch(Coroutine *from_, + CoroutineGThread *from = DO_UPCAST(CoroutineGThread, base, from_); + CoroutineGThread *to = DO_UPCAST(CoroutineGThread, base, to_); + +- g_static_mutex_lock(&coroutine_lock); ++ g_mutex_lock(&coroutine_lock); + from->runnable = false; + from->action = action; + to->runnable = true; + to->action = action; +- g_cond_broadcast(coroutine_cond); ++ g_cond_broadcast(&coroutine_cond); + + if (action != COROUTINE_TERMINATE) { + coroutine_wait_runnable_locked(from); + } +- g_static_mutex_unlock(&coroutine_lock); ++ g_mutex_unlock(&coroutine_lock); + return from->action; + } + +diff --git a/include/glib-compat.h b/include/glib-compat.h +index 1280fb2..4ae0671 100644 +--- a/include/glib-compat.h ++++ b/include/glib-compat.h +@@ -5,6 +5,8 @@ + * + * Authors: + * Anthony Liguori ++ * Michael Tokarev ++ * Paolo Bonzini + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. +@@ -43,4 +45,121 @@ static inline gint g_poll(GPollFD *fds, guint nfds, gint timeout) + } + #endif + ++#if !GLIB_CHECK_VERSION(2, 31, 0) ++/* before glib-2.31, GMutex and GCond was dynamic-only (there was a separate ++ * GStaticMutex, but it didn't work with condition variables). ++ * ++ * Our implementation uses GOnce to fake a static implementation that does ++ * not require separate initialization. ++ * We need to rename the types to avoid passing our CompatGMutex/CompatGCond ++ * by mistake to a function that expects GMutex/GCond. However, for ease ++ * of use we keep the GLib function names. GLib uses macros for the ++ * implementation, we use inline functions instead and undefine the macros. ++ */ ++ ++typedef struct CompatGMutex { ++ GOnce once; ++} CompatGMutex; ++ ++typedef struct CompatGCond { ++ GOnce once; ++} CompatGCond; ++ ++static inline gpointer do_g_mutex_new(gpointer unused) ++{ ++ return (gpointer) g_mutex_new(); ++} ++ ++static inline void g_mutex_init(CompatGMutex *mutex) ++{ ++ mutex->once = (GOnce) G_ONCE_INIT; ++} ++ ++static inline void g_mutex_clear(CompatGMutex *mutex) ++{ ++ assert(mutex->once.status != G_ONCE_STATUS_PROGRESS); ++ if (mutex->once.retval) { ++ g_mutex_free((GMutex *) mutex->once.retval); ++ } ++ mutex->once = (GOnce) G_ONCE_INIT; ++} ++ ++static inline void (g_mutex_lock)(CompatGMutex *mutex) ++{ ++ g_once(&mutex->once, do_g_mutex_new, NULL); ++ g_mutex_lock((GMutex *) mutex->once.retval); ++} ++#undef g_mutex_lock ++ ++static inline gboolean (g_mutex_trylock)(CompatGMutex *mutex) ++{ ++ g_once(&mutex->once, do_g_mutex_new, NULL); ++ return g_mutex_trylock((GMutex *) mutex->once.retval); ++} ++#undef g_mutex_trylock ++ ++ ++static inline void (g_mutex_unlock)(CompatGMutex *mutex) ++{ ++ g_mutex_unlock((GMutex *) mutex->once.retval); ++} ++#undef g_mutex_unlock ++ ++static inline gpointer do_g_cond_new(gpointer unused) ++{ ++ return (gpointer) g_cond_new(); ++} ++ ++static inline void g_cond_init(CompatGCond *cond) ++{ ++ cond->once = (GOnce) G_ONCE_INIT; ++} ++ ++static inline void g_cond_clear(CompatGCond *cond) ++{ ++ assert(cond->once.status != G_ONCE_STATUS_PROGRESS); ++ if (cond->once.retval) { ++ g_cond_free((GCond *) cond->once.retval); ++ } ++ cond->once = (GOnce) G_ONCE_INIT; ++} ++ ++static inline void (g_cond_wait)(CompatGCond *cond, CompatGMutex *mutex) ++{ ++ assert(mutex->once.status != G_ONCE_STATUS_PROGRESS); ++ g_once(&cond->once, do_g_cond_new, NULL); ++ g_cond_wait((GCond *) cond->once.retval, (GMutex *) mutex->once.retval); ++} ++#undef g_cond_wait ++ ++static inline void (g_cond_broadcast)(CompatGCond *cond) ++{ ++ g_once(&cond->once, do_g_cond_new, NULL); ++ g_cond_broadcast((GCond *) cond->once.retval); ++} ++#undef g_cond_broadcast ++ ++static inline void (g_cond_signal)(CompatGCond *cond) ++{ ++ g_once(&cond->once, do_g_cond_new, NULL); ++ g_cond_signal((GCond *) cond->once.retval); ++} ++#undef g_cond_signal ++ ++ ++/* before 2.31 there was no g_thread_new() */ ++static inline GThread *g_thread_new(const char *name, ++ GThreadFunc func, gpointer data) ++{ ++ GThread *thread = g_thread_create(func, data, TRUE, NULL); ++ if (!thread) { ++ g_error("creating thread"); ++ } ++ return thread; ++} ++#else ++#define CompatGMutex GMutex ++#define CompatGCond GCond ++#endif /* glib 2.31 */ ++ + #endif +diff --git a/trace/simple.c b/trace/simple.c +index 1584bf7..8fc96fe 100644 +--- a/trace/simple.c ++++ b/trace/simple.c +@@ -40,28 +40,9 @@ + * Trace records are written out by a dedicated thread. The thread waits for + * records to become available, writes them out, and then waits again. + */ +-#if GLIB_CHECK_VERSION(2, 32, 0) +-static GMutex trace_lock; +-#define lock_trace_lock() g_mutex_lock(&trace_lock) +-#define unlock_trace_lock() g_mutex_unlock(&trace_lock) +-#define get_trace_lock_mutex() (&trace_lock) +-#else +-static GStaticMutex trace_lock = G_STATIC_MUTEX_INIT; +-#define lock_trace_lock() g_static_mutex_lock(&trace_lock) +-#define unlock_trace_lock() g_static_mutex_unlock(&trace_lock) +-#define get_trace_lock_mutex() g_static_mutex_get_mutex(&trace_lock) +-#endif +- +-/* g_cond_new() was deprecated in glib 2.31 but we still need to support it */ +-#if GLIB_CHECK_VERSION(2, 31, 0) +-static GCond the_trace_available_cond; +-static GCond the_trace_empty_cond; +-static GCond *trace_available_cond = &the_trace_available_cond; +-static GCond *trace_empty_cond = &the_trace_empty_cond; +-#else +-static GCond *trace_available_cond; +-static GCond *trace_empty_cond; +-#endif ++static CompatGMutex trace_lock; ++static CompatGCond trace_available_cond; ++static CompatGCond trace_empty_cond; + + static bool trace_available; + static bool trace_writeout_enabled; +@@ -151,26 +132,26 @@ static bool get_trace_record(unsigned int idx, TraceRecord **recordptr) + */ + static void flush_trace_file(bool wait) + { +- lock_trace_lock(); ++ g_mutex_lock(&trace_lock); + trace_available = true; +- g_cond_signal(trace_available_cond); ++ g_cond_signal(&trace_available_cond); + + if (wait) { +- g_cond_wait(trace_empty_cond, get_trace_lock_mutex()); ++ g_cond_wait(&trace_empty_cond, &trace_lock); + } + +- unlock_trace_lock(); ++ g_mutex_unlock(&trace_lock); + } + + static void wait_for_trace_records_available(void) + { +- lock_trace_lock(); ++ g_mutex_lock(&trace_lock); + while (!(trace_available && trace_writeout_enabled)) { +- g_cond_signal(trace_empty_cond); +- g_cond_wait(trace_available_cond, get_trace_lock_mutex()); ++ g_cond_signal(&trace_empty_cond); ++ g_cond_wait(&trace_available_cond, &trace_lock); + } + trace_available = false; +- unlock_trace_lock(); ++ g_mutex_unlock(&trace_lock); + } + + static gpointer writeout_thread(gpointer opaque) +@@ -399,11 +380,7 @@ static GThread *trace_thread_create(GThreadFunc fn) + pthread_sigmask(SIG_SETMASK, &set, &oldset); + #endif + +-#if GLIB_CHECK_VERSION(2, 31, 0) + thread = g_thread_new("trace-thread", fn, NULL); +-#else +- thread = g_thread_create(fn, NULL, FALSE, NULL); +-#endif + + #ifndef _WIN32 + pthread_sigmask(SIG_SETMASK, &oldset, NULL); +@@ -418,11 +395,6 @@ bool trace_backend_init(const char *events, const char *file) + + trace_pid = getpid(); + +-#if !GLIB_CHECK_VERSION(2, 31, 0) +- trace_available_cond = g_cond_new(); +- trace_empty_cond = g_cond_new(); +-#endif +- + thread = trace_thread_create(writeout_thread); + if (!thread) { + fprintf(stderr, "warning: unable to initialize simple trace backend\n"); diff --git a/0114-libcacard-replace-pstrcpy-with-memcpy.patch b/0114-libcacard-replace-pstrcpy-with-memcpy.patch new file mode 100644 index 0000000..25ec2dd --- /dev/null +++ b/0114-libcacard-replace-pstrcpy-with-memcpy.patch @@ -0,0 +1,38 @@ +From c916d06403eec41a92eabf52b31102d3b7068da8 Mon Sep 17 00:00:00 2001 +From: Michael Tokarev +Date: Fri, 2 May 2014 18:35:59 +0400 +Subject: [PATCH] libcacard: replace pstrcpy() with memcpy() + +Commit 2e679780ae86c6ca8 replaced strncpy() with pstrcpy() +in one place in libcacard. This is a qemu-specific function, +while libcacard is a stand-alone library (or tries to be). +But since we know the exact length of the string to copy, +and know that it definitely will fit in the destination +buffer, use memcpy() instead, and null-terminate the string +after that. + +An alternative is to use g_strlcpy() or strncpy(), but memcpy() +is more than adequate in this place. + +Signed-off-by: Michael Tokarev +Cc: qemu-trivial@nongnu.org +Cc: Alon Levy +(cherry picked from commit a22f8f38942623dc473bf5ced5b4117b8bdf4821) +--- + libcacard/vcard_emul_nss.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/libcacard/vcard_emul_nss.c b/libcacard/vcard_emul_nss.c +index ee2dfae..e2b196d 100644 +--- a/libcacard/vcard_emul_nss.c ++++ b/libcacard/vcard_emul_nss.c +@@ -1162,7 +1162,8 @@ vcard_emul_options(const char *args) + NEXT_TOKEN(vname) + NEXT_TOKEN(type_params) + type_params_length = MIN(type_params_length, sizeof(type_str)-1); +- pstrcpy(type_str, type_params_length, type_params); ++ memcpy(type_str, type_params, type_params_length); ++ type_str[type_params_length] = '\0'; + type = vcard_emul_type_from_string(type_str); + + NEXT_TOKEN(type_params) diff --git a/0115-libcacard-g_malloc-cleanups.patch b/0115-libcacard-g_malloc-cleanups.patch new file mode 100644 index 0000000..5b2d98d --- /dev/null +++ b/0115-libcacard-g_malloc-cleanups.patch @@ -0,0 +1,236 @@ +From 118436ff47d7269f4bf3e3c1cd83df4b44b7d5c2 Mon Sep 17 00:00:00 2001 +From: Michael Tokarev +Date: Thu, 8 May 2014 19:51:01 +0400 +Subject: [PATCH] libcacard: g_malloc cleanups + +This patch replaces g_malloc() in libcacard into g_new() +or g_new0() where appropriate (removing some init-to-zero +surrounding code), g_malloc+memcpy into g_memdup() and the +like. + +Signed-off-by: Michael Tokarev +Reviewed-by: Alon Levy +(cherry picked from commit 78a4b8d2051bff8e8794e9419b7925122212b096) +--- + libcacard/cac.c | 11 +++-------- + libcacard/card_7816.c | 11 +++++------ + libcacard/event.c | 2 +- + libcacard/vcard.c | 22 +++++----------------- + libcacard/vcard_emul_nss.c | 12 ++++++------ + libcacard/vreader.c | 11 +++-------- + 6 files changed, 23 insertions(+), 46 deletions(-) + +diff --git a/libcacard/cac.c b/libcacard/cac.c +index 74ef3e3..122129e 100644 +--- a/libcacard/cac.c ++++ b/libcacard/cac.c +@@ -310,16 +310,11 @@ static VCardAppletPrivate * + cac_new_pki_applet_private(const unsigned char *cert, + int cert_len, VCardKey *key) + { +- CACPKIAppletData *pki_applet_data = NULL; +- VCardAppletPrivate *applet_private = NULL; +- applet_private = (VCardAppletPrivate *)g_malloc(sizeof(VCardAppletPrivate)); ++ CACPKIAppletData *pki_applet_data; ++ VCardAppletPrivate *applet_private; + ++ applet_private = g_new0(VCardAppletPrivate, 1); + pki_applet_data = &(applet_private->u.pki_data); +- pki_applet_data->cert_buffer = NULL; +- pki_applet_data->cert_buffer_len = 0; +- pki_applet_data->sign_buffer = NULL; +- pki_applet_data->sign_buffer_len = 0; +- pki_applet_data->key = NULL; + pki_applet_data->cert = (unsigned char *)g_malloc(cert_len+1); + /* + * if we want to support compression, then we simply change the 0 to a 1 +diff --git a/libcacard/card_7816.c b/libcacard/card_7816.c +index c28bb60..bca8c4a 100644 +--- a/libcacard/card_7816.c ++++ b/libcacard/card_7816.c +@@ -51,7 +51,7 @@ vcard_response_new_data(unsigned char *buf, int len) + { + VCardResponse *new_response; + +- new_response = (VCardResponse *)g_malloc(sizeof(VCardResponse)); ++ new_response = g_new(VCardResponse, 1); + new_response->b_data = g_malloc(len + 2); + memcpy(new_response->b_data, buf, len); + new_response->b_total_len = len+2; +@@ -132,7 +132,7 @@ vcard_response_new_status(vcard_7816_status_t status) + { + VCardResponse *new_response; + +- new_response = (VCardResponse *)g_malloc(sizeof(VCardResponse)); ++ new_response = g_new(VCardResponse, 1); + new_response->b_data = &new_response->b_sw1; + new_response->b_len = 0; + new_response->b_total_len = 2; +@@ -149,7 +149,7 @@ vcard_response_new_status_bytes(unsigned char sw1, unsigned char sw2) + { + VCardResponse *new_response; + +- new_response = (VCardResponse *)g_malloc(sizeof(VCardResponse)); ++ new_response = g_new(VCardResponse, 1); + new_response->b_data = &new_response->b_sw1; + new_response->b_len = 0; + new_response->b_total_len = 2; +@@ -336,9 +336,8 @@ vcard_apdu_new(unsigned char *raw_apdu, int len, vcard_7816_status_t *status) + return NULL; + } + +- new_apdu = (VCardAPDU *)g_malloc(sizeof(VCardAPDU)); +- new_apdu->a_data = g_malloc(len); +- memcpy(new_apdu->a_data, raw_apdu, len); ++ new_apdu = g_new(VCardAPDU, 1); ++ new_apdu->a_data = g_memdup(raw_apdu, len); + new_apdu->a_len = len; + *status = vcard_apdu_set_class(new_apdu); + if (*status != VCARD7816_STATUS_SUCCESS) { +diff --git a/libcacard/event.c b/libcacard/event.c +index 2d7500f..a2e6c7d 100644 +--- a/libcacard/event.c ++++ b/libcacard/event.c +@@ -17,7 +17,7 @@ vevent_new(VEventType type, VReader *reader, VCard *card) + { + VEvent *new_vevent; + +- new_vevent = (VEvent *)g_malloc(sizeof(VEvent)); ++ new_vevent = g_new(VEvent, 1); + new_vevent->next = NULL; + new_vevent->type = type; + new_vevent->reader = vreader_reference(reader); +diff --git a/libcacard/vcard.c b/libcacard/vcard.c +index 539177b..227e477 100644 +--- a/libcacard/vcard.c ++++ b/libcacard/vcard.c +@@ -37,9 +37,8 @@ vcard_buffer_response_new(unsigned char *buffer, int size) + { + VCardBufferResponse *new_buffer; + +- new_buffer = (VCardBufferResponse *)g_malloc(sizeof(VCardBufferResponse)); +- new_buffer->buffer = (unsigned char *)g_malloc(size); +- memcpy(new_buffer->buffer, buffer, size); ++ new_buffer = g_new(VCardBufferResponse, 1); ++ new_buffer->buffer = (unsigned char *)g_memdup(buffer, size); + new_buffer->buffer_len = size; + new_buffer->current = new_buffer->buffer; + new_buffer->len = size; +@@ -102,15 +101,11 @@ vcard_new_applet(VCardProcessAPDU applet_process_function, + { + VCardApplet *applet; + +- applet = (VCardApplet *)g_malloc(sizeof(VCardApplet)); +- applet->next = NULL; +- applet->applet_private = NULL; +- applet->applet_private_free = NULL; ++ applet = g_new0(VCardApplet, 1); + applet->process_apdu = applet_process_function; + applet->reset_applet = applet_reset_function; + +- applet->aid = g_malloc(aid_len); +- memcpy(applet->aid, aid, aid_len); ++ applet->aid = g_memdup(aid, aid_len); + applet->aid_len = aid_len; + return applet; + } +@@ -149,18 +144,11 @@ VCard * + vcard_new(VCardEmul *private, VCardEmulFree private_free) + { + VCard *new_card; +- int i; + +- new_card = (VCard *)g_malloc(sizeof(VCard)); +- new_card->applet_list = NULL; +- for (i = 0; i < MAX_CHANNEL; i++) { +- new_card->current_applet[i] = NULL; +- } +- new_card->vcard_buffer_response = NULL; ++ new_card = g_new0(VCard, 1); + new_card->type = VCARD_VM; + new_card->vcard_private = private; + new_card->vcard_private_free = private_free; +- new_card->vcard_get_atr = NULL; + new_card->reference_count = 1; + return new_card; + } +diff --git a/libcacard/vcard_emul_nss.c b/libcacard/vcard_emul_nss.c +index e2b196d..75b9d79 100644 +--- a/libcacard/vcard_emul_nss.c ++++ b/libcacard/vcard_emul_nss.c +@@ -94,9 +94,9 @@ static void + vcard_emul_alloc_arrays(unsigned char ***certsp, int **cert_lenp, + VCardKey ***keysp, int cert_count) + { +- *certsp = (unsigned char **)g_malloc(sizeof(unsigned char *)*cert_count); +- *cert_lenp = (int *)g_malloc(sizeof(int)*cert_count); +- *keysp = (VCardKey **)g_malloc(sizeof(VCardKey *)*cert_count); ++ *certsp = g_new(unsigned char *, cert_count); ++ *cert_lenp = g_new(int, cert_count); ++ *keysp = g_new(VCardKey *, cert_count); + } + + /* +@@ -139,7 +139,7 @@ vcard_emul_make_key(PK11SlotInfo *slot, CERTCertificate *cert) + { + VCardKey *key; + +- key = (VCardKey *)g_malloc(sizeof(VCardKey)); ++ key = g_new(VCardKey, 1); + key->slot = PK11_ReferenceSlot(slot); + key->cert = CERT_DupCertificate(cert); + /* NOTE: if we aren't logged into the token, this could return NULL */ +@@ -449,7 +449,7 @@ vreader_emul_new(PK11SlotInfo *slot, VCardEmulType type, const char *params) + { + VReaderEmul *new_reader_emul; + +- new_reader_emul = (VReaderEmul *)g_malloc(sizeof(VReaderEmul)); ++ new_reader_emul = g_new(VReaderEmul, 1); + + new_reader_emul->slot = PK11_ReferenceSlot(slot); + new_reader_emul->default_type = type; +@@ -1189,7 +1189,7 @@ vcard_emul_options(const char *args) + g_strndup(type_params, type_params_length); + count = count_tokens(args, ',', ')') + 1; + vreaderOpt->cert_count = count; +- vreaderOpt->cert_name = (char **)g_malloc(count*sizeof(char *)); ++ vreaderOpt->cert_name = g_new(char *, count); + for (i = 0; i < count; i++) { + const char *cert = args; + args = strpbrk(args, ",)"); +diff --git a/libcacard/vreader.c b/libcacard/vreader.c +index 5793d73..215a2f6 100644 +--- a/libcacard/vreader.c ++++ b/libcacard/vreader.c +@@ -115,7 +115,7 @@ vreader_new(const char *name, VReaderEmul *private, + { + VReader *reader; + +- reader = (VReader *)g_malloc(sizeof(VReader)); ++ reader = g_new(VReader, 1); + qemu_mutex_init(&reader->lock); + reader->reference_count = 1; + reader->name = g_strdup(name); +@@ -312,10 +312,7 @@ vreader_list_entry_new(VReader *reader) + { + VReaderListEntry *new_reader_list_entry; + +- new_reader_list_entry = (VReaderListEntry *) +- g_malloc(sizeof(VReaderListEntry)); +- new_reader_list_entry->next = NULL; +- new_reader_list_entry->prev = NULL; ++ new_reader_list_entry = g_new0(VReaderListEntry, 1); + new_reader_list_entry->reader = vreader_reference(reader); + return new_reader_list_entry; + } +@@ -336,9 +333,7 @@ vreader_list_new(void) + { + VReaderList *new_reader_list; + +- new_reader_list = (VReaderList *)g_malloc(sizeof(VReaderList)); +- new_reader_list->head = NULL; +- new_reader_list->tail = NULL; ++ new_reader_list = g_new0(VReaderList, 1); + return new_reader_list; + } + diff --git a/0116-vscclient-use-glib-thread-primitives-not-qemu.patch b/0116-vscclient-use-glib-thread-primitives-not-qemu.patch new file mode 100644 index 0000000..018f9e6 --- /dev/null +++ b/0116-vscclient-use-glib-thread-primitives-not-qemu.patch @@ -0,0 +1,218 @@ +From 4a609afa4206d7af9fe2c8dcfbe7850509701aff Mon Sep 17 00:00:00 2001 +From: Michael Tokarev +Date: Thu, 8 May 2014 12:30:47 +0400 +Subject: [PATCH] vscclient: use glib thread primitives not qemu + +Use glib-provided thread primitives in vscclient instead of +qemu ones, and do not use qemu sockets in there (open-code +call to WSAStartup() for windows to initialize things). + +This way, vscclient becomes more stand-alone, independent on +qemu internals. + +Signed-off-by: Michael Tokarev +Reviewed-by: Alon Levy +Tested-by: Alon Levy +Signed-off-by: Paolo Bonzini +(cherry picked from commit 2a0c46da967e5dc8cfe73b1b6fe7a1600c04f461) +--- + libcacard/vscclient.c | 70 +++++++++++++++++++++++++++------------------------ + 1 file changed, 37 insertions(+), 33 deletions(-) + +diff --git a/libcacard/vscclient.c b/libcacard/vscclient.c +index 3477ab3..598206b 100644 +--- a/libcacard/vscclient.c ++++ b/libcacard/vscclient.c +@@ -12,12 +12,10 @@ + + #ifndef _WIN32 + #include ++#define closesocket(x) close(x) + #endif +-#include + + #include "qemu-common.h" +-#include "qemu/thread.h" +-#include "qemu/sockets.h" + + #include "vscard_common.h" + +@@ -54,7 +52,7 @@ print_usage(void) { + + static GIOChannel *channel_socket; + static GByteArray *socket_to_send; +-static QemuMutex socket_to_send_lock; ++static CompatGMutex socket_to_send_lock; + static guint socket_tag; + + static void +@@ -103,7 +101,7 @@ send_msg( + ) { + VSCMsgHeader mhHeader; + +- qemu_mutex_lock(&socket_to_send_lock); ++ g_mutex_lock(&socket_to_send_lock); + + if (verbose > 10) { + printf("sending type=%d id=%u, len =%u (0x%x)\n", +@@ -117,18 +115,18 @@ send_msg( + g_byte_array_append(socket_to_send, (guint8 *)msg, length); + g_idle_add(socket_prepare_sending, NULL); + +- qemu_mutex_unlock(&socket_to_send_lock); ++ g_mutex_unlock(&socket_to_send_lock); + + return 0; + } + + static VReader *pending_reader; +-static QemuMutex pending_reader_lock; +-static QemuCond pending_reader_condition; ++static CompatGMutex pending_reader_lock; ++static CompatGCond pending_reader_condition; + + #define MAX_ATR_LEN 40 +-static void * +-event_thread(void *arg) ++static gpointer ++event_thread(gpointer arg) + { + unsigned char atr[MAX_ATR_LEN]; + int atr_len = MAX_ATR_LEN; +@@ -149,20 +147,20 @@ event_thread(void *arg) + /* ignore events from readers qemu has rejected */ + /* if qemu is still deciding on this reader, wait to see if need to + * forward this event */ +- qemu_mutex_lock(&pending_reader_lock); ++ g_mutex_lock(&pending_reader_lock); + if (!pending_reader || (pending_reader != event->reader)) { + /* wasn't for a pending reader, this reader has already been + * rejected by qemu */ +- qemu_mutex_unlock(&pending_reader_lock); ++ g_mutex_unlock(&pending_reader_lock); + vevent_delete(event); + continue; + } + /* this reader hasn't been told its status from qemu yet, wait for + * that status */ + while (pending_reader != NULL) { +- qemu_cond_wait(&pending_reader_condition, &pending_reader_lock); ++ g_cond_wait(&pending_reader_condition, &pending_reader_lock); + } +- qemu_mutex_unlock(&pending_reader_lock); ++ g_mutex_unlock(&pending_reader_lock); + /* now recheck the id */ + reader_id = vreader_get_id(event->reader); + if (reader_id == VSCARD_UNDEFINED_READER_ID) { +@@ -178,12 +176,12 @@ event_thread(void *arg) + /* wait until qemu has responded to our first reader insert + * before we send a second. That way we won't confuse the responses + * */ +- qemu_mutex_lock(&pending_reader_lock); ++ g_mutex_lock(&pending_reader_lock); + while (pending_reader != NULL) { +- qemu_cond_wait(&pending_reader_condition, &pending_reader_lock); ++ g_cond_wait(&pending_reader_condition, &pending_reader_lock); + } + pending_reader = vreader_reference(event->reader); +- qemu_mutex_unlock(&pending_reader_lock); ++ g_mutex_unlock(&pending_reader_lock); + reader_name = vreader_get_name(event->reader); + if (verbose > 10) { + printf(" READER INSERT: %s\n", reader_name); +@@ -246,7 +244,6 @@ on_host_init(VSCMsgHeader *mhHeader, VSCMsgInit *incoming) + int num_capabilities = + 1 + ((mhHeader->length - sizeof(VSCMsgInit)) / sizeof(uint32_t)); + int i; +- QemuThread thread_id; + + incoming->version = ntohl(incoming->version); + if (incoming->version != VSCARD_VERSION) { +@@ -269,7 +266,7 @@ on_host_init(VSCMsgHeader *mhHeader, VSCMsgInit *incoming) + send_msg(VSC_ReaderRemove, VSCARD_MINIMAL_READER_ID, NULL, 0); + /* launch the event_thread. This will trigger reader adds for all the + * existing readers */ +- qemu_thread_create(&thread_id, "vsc/event", event_thread, NULL, 0); ++ g_thread_new("vsc/event", event_thread, NULL); + return 0; + } + +@@ -379,26 +376,26 @@ do_socket_read(GIOChannel *source, + case VSC_Error: + error_msg = (VSCMsgError *) pbSendBuffer; + if (error_msg->code == VSC_SUCCESS) { +- qemu_mutex_lock(&pending_reader_lock); ++ g_mutex_lock(&pending_reader_lock); + if (pending_reader) { + vreader_set_id(pending_reader, mhHeader.reader_id); + vreader_free(pending_reader); + pending_reader = NULL; +- qemu_cond_signal(&pending_reader_condition); ++ g_cond_signal(&pending_reader_condition); + } +- qemu_mutex_unlock(&pending_reader_lock); ++ g_mutex_unlock(&pending_reader_lock); + break; + } + printf("warning: qemu refused to add reader\n"); + if (error_msg->code == VSC_CANNOT_ADD_MORE_READERS) { + /* clear pending reader, qemu can't handle any more */ +- qemu_mutex_lock(&pending_reader_lock); ++ g_mutex_lock(&pending_reader_lock); + if (pending_reader) { + pending_reader = NULL; + /* make sure the event loop doesn't hang */ +- qemu_cond_signal(&pending_reader_condition); ++ g_cond_signal(&pending_reader_condition); + } +- qemu_mutex_unlock(&pending_reader_lock); ++ g_mutex_unlock(&pending_reader_lock); + } + break; + case VSC_Init: +@@ -602,7 +599,7 @@ connect_to_qemu( + struct addrinfo *server; + int ret, sock; + +- sock = qemu_socket(AF_INET, SOCK_STREAM, 0); ++ sock = socket(AF_INET, SOCK_STREAM, 0); + if (sock < 0) { + /* Error */ + fprintf(stderr, "Error opening socket!\n"); +@@ -655,8 +652,20 @@ main( + int cert_count = 0; + int c, sock; + +- if (socket_init() != 0) ++#ifdef _WIN32 ++ WSADATA Data; ++ ++ if (WSAStartup(MAKEWORD(2, 2), &Data) != 0) { ++ c = WSAGetLastError(); ++ fprintf(stderr, "WSAStartup: %d\n", c); + return 1; ++ } ++#endif ++#if !GLIB_CHECK_VERSION(2, 31, 0) ++ if (!g_thread_supported()) { ++ g_thread_init(NULL); ++ } ++#endif + + while ((c = getopt(argc, argv, "c:e:pd:")) != -1) { + switch (c) { +@@ -723,13 +732,8 @@ main( + } + + socket_to_send = g_byte_array_new(); +- qemu_mutex_init(&socket_to_send_lock); +- qemu_mutex_init(&pending_reader_lock); +- qemu_cond_init(&pending_reader_condition); +- + vcard_emul_init(command_line_options); +- +- loop = g_main_loop_new(NULL, true); ++ loop = g_main_loop_new(NULL, TRUE); + + printf("> "); + fflush(stdout); diff --git a/0117-libcacard-replace-qemu-thread-primitives-with-glib-o.patch b/0117-libcacard-replace-qemu-thread-primitives-with-glib-o.patch new file mode 100644 index 0000000..72fc8ac --- /dev/null +++ b/0117-libcacard-replace-qemu-thread-primitives-with-glib-o.patch @@ -0,0 +1,204 @@ +From 95d830ad782262bac47e4cc368e8dff108b789f1 Mon Sep 17 00:00:00 2001 +From: Michael Tokarev +Date: Thu, 8 May 2014 12:30:48 +0400 +Subject: [PATCH] libcacard: replace qemu thread primitives with glib ones + +Replace QemuMutex with GMutex and QemuCond with GCond +(with corresponding function changes), to make libcacard +independent of qemu internal functions. + +After this step, none of libcacard internals use any +qemu-provided symbols. Maybe it's a good idea to +stop including qemu-common.h internally too. + +Signed-off-by: Michael Tokarev +Reviewed-by: Alon Levy +Tested-by: Alon Levy +Signed-off-by: Paolo Bonzini +(cherry picked from commit fd25c0e6dd1ed2aa932fa7ef814b32457bf270fd) +--- + libcacard/Makefile | 8 +------- + libcacard/event.c | 23 ++++++++++------------- + libcacard/vreader.c | 18 ++++++++---------- + 3 files changed, 19 insertions(+), 30 deletions(-) + +diff --git a/libcacard/Makefile b/libcacard/Makefile +index 6b06448..89a5942 100644 +--- a/libcacard/Makefile ++++ b/libcacard/Makefile +@@ -3,13 +3,7 @@ libcacard_includedir=$(includedir)/cacard + TOOLS += vscclient$(EXESUF) + + # objects linked into a shared library, built with libtool with -fPIC if required +-libcacard-obj-y = $(stub-obj-y) $(libcacard-y) +-libcacard-obj-y += util/osdep.o util/cutils.o util/qemu-timer-common.o +-libcacard-obj-y += util/error.o util/qemu-error.o +-libcacard-obj-$(CONFIG_WIN32) += util/oslib-win32.o util/qemu-thread-win32.o +-libcacard-obj-$(CONFIG_POSIX) += util/oslib-posix.o util/qemu-thread-posix.o +-libcacard-obj-y += $(filter trace/%, $(util-obj-y)) +- ++libcacard-obj-y = $(libcacard-y) + libcacard-lobj-y=$(patsubst %.o,%.lo,$(libcacard-obj-y)) + + # libtool will build the .o files, too +diff --git a/libcacard/event.c b/libcacard/event.c +index a2e6c7d..4c551e4 100644 +--- a/libcacard/event.c ++++ b/libcacard/event.c +@@ -6,7 +6,6 @@ + */ + + #include "qemu-common.h" +-#include "qemu/thread.h" + + #include "vcard.h" + #include "vreader.h" +@@ -43,13 +42,11 @@ vevent_delete(VEvent *vevent) + + static VEvent *vevent_queue_head; + static VEvent *vevent_queue_tail; +-static QemuMutex vevent_queue_lock; +-static QemuCond vevent_queue_condition; ++static CompatGMutex vevent_queue_lock; ++static CompatGCond vevent_queue_condition; + + void vevent_queue_init(void) + { +- qemu_mutex_init(&vevent_queue_lock); +- qemu_cond_init(&vevent_queue_condition); + vevent_queue_head = vevent_queue_tail = NULL; + } + +@@ -57,7 +54,7 @@ void + vevent_queue_vevent(VEvent *vevent) + { + vevent->next = NULL; +- qemu_mutex_lock(&vevent_queue_lock); ++ g_mutex_lock(&vevent_queue_lock); + if (vevent_queue_head) { + assert(vevent_queue_tail); + vevent_queue_tail->next = vevent; +@@ -65,8 +62,8 @@ vevent_queue_vevent(VEvent *vevent) + vevent_queue_head = vevent; + } + vevent_queue_tail = vevent; +- qemu_cond_signal(&vevent_queue_condition); +- qemu_mutex_unlock(&vevent_queue_lock); ++ g_cond_signal(&vevent_queue_condition); ++ g_mutex_unlock(&vevent_queue_lock); + } + + /* must have lock */ +@@ -86,11 +83,11 @@ VEvent *vevent_wait_next_vevent(void) + { + VEvent *vevent; + +- qemu_mutex_lock(&vevent_queue_lock); ++ g_mutex_lock(&vevent_queue_lock); + while ((vevent = vevent_dequeue_vevent()) == NULL) { +- qemu_cond_wait(&vevent_queue_condition, &vevent_queue_lock); ++ g_cond_wait(&vevent_queue_condition, &vevent_queue_lock); + } +- qemu_mutex_unlock(&vevent_queue_lock); ++ g_mutex_unlock(&vevent_queue_lock); + return vevent; + } + +@@ -98,9 +95,9 @@ VEvent *vevent_get_next_vevent(void) + { + VEvent *vevent; + +- qemu_mutex_lock(&vevent_queue_lock); ++ g_mutex_lock(&vevent_queue_lock); + vevent = vevent_dequeue_vevent(); +- qemu_mutex_unlock(&vevent_queue_lock); ++ g_mutex_unlock(&vevent_queue_lock); + return vevent; + } + +diff --git a/libcacard/vreader.c b/libcacard/vreader.c +index 215a2f6..75b5b28 100644 +--- a/libcacard/vreader.c ++++ b/libcacard/vreader.c +@@ -9,10 +9,8 @@ + #undef G_LOG_DOMAIN + #endif + #define G_LOG_DOMAIN "libcacard" +-#include + + #include "qemu-common.h" +-#include "qemu/thread.h" + + #include "vcard.h" + #include "vcard_emul.h" +@@ -28,7 +26,7 @@ struct VReaderStruct { + VCard *card; + char *name; + vreader_id_t id; +- QemuMutex lock; ++ CompatGMutex lock; + VReaderEmul *reader_private; + VReaderEmulFree reader_private_free; + }; +@@ -97,13 +95,13 @@ apdu_ins_to_string(int ins) + static inline void + vreader_lock(VReader *reader) + { +- qemu_mutex_lock(&reader->lock); ++ g_mutex_lock(&reader->lock); + } + + static inline void + vreader_unlock(VReader *reader) + { +- qemu_mutex_unlock(&reader->lock); ++ g_mutex_unlock(&reader->lock); + } + + /* +@@ -116,7 +114,7 @@ vreader_new(const char *name, VReaderEmul *private, + VReader *reader; + + reader = g_new(VReader, 1); +- qemu_mutex_init(&reader->lock); ++ g_mutex_init(&reader->lock); + reader->reference_count = 1; + reader->name = g_strdup(name); + reader->card = NULL; +@@ -152,6 +150,7 @@ vreader_free(VReader *reader) + return; + } + vreader_unlock(reader); ++ g_mutex_clear(&reader->lock); + if (reader->card) { + vcard_free(reader->card); + } +@@ -408,25 +407,24 @@ vreader_dequeue(VReaderList *list, VReaderListEntry *entry) + } + + static VReaderList *vreader_list; +-static QemuMutex vreader_list_mutex; ++static CompatGMutex vreader_list_mutex; + + static void + vreader_list_init(void) + { + vreader_list = vreader_list_new(); +- qemu_mutex_init(&vreader_list_mutex); + } + + static void + vreader_list_lock(void) + { +- qemu_mutex_lock(&vreader_list_mutex); ++ g_mutex_lock(&vreader_list_mutex); + } + + static void + vreader_list_unlock(void) + { +- qemu_mutex_unlock(&vreader_list_mutex); ++ g_mutex_unlock(&vreader_list_mutex); + } + + static VReaderList * diff --git a/qemu.spec b/qemu.spec index 1602a24..2b1d1f2 100644 --- a/qemu.spec +++ b/qemu.spec @@ -158,7 +158,7 @@ Summary: QEMU is a FAST! processor emulator Name: qemu Version: 2.0.0 -Release: 6%{?dist} +Release: 7%{?dist} Epoch: 2 License: GPLv2+ and LGPLv2+ and BSD Group: Development/Tools @@ -236,6 +236,18 @@ Patch0105: 0105-qcow1-Stricter-backing-file-length-check.patch # CVE-2014-3461: Issues in USB post load checks (bz #1097260, bz # #1096821) Patch0106: 0106-usb-fix-up-post-load-checks.patch +# Don't use libtool on dtrace, fixes rawhide build (bz #1106968) +Patch0107: 0107-trace-add-pid-field-to-simpletrace-record.patch +Patch0108: 0108-simpletrace-add-support-for-trace-record-pid-field.patch +Patch0109: 0109-trace-Replace-error-with-warning-if-event-is-not-def.patch +Patch0110: 0110-do-not-call-g_thread_init-for-glib-2.31.patch +Patch0111: 0111-glib-move-g_poll-replacement-into-glib-compat.h.patch +Patch0112: 0112-glib-fix-g_poll-early-timeout-on-windows.patch +Patch0113: 0113-glib-compat.h-add-new-thread-API-emulation-on-top-of.patch +Patch0114: 0114-libcacard-replace-pstrcpy-with-memcpy.patch +Patch0115: 0115-libcacard-g_malloc-cleanups.patch +Patch0116: 0116-vscclient-use-glib-thread-primitives-not-qemu.patch +Patch0117: 0117-libcacard-replace-qemu-thread-primitives-with-glib-o.patch BuildRequires: SDL-devel BuildRequires: zlib-devel @@ -796,6 +808,18 @@ CAC emulation development files. # CVE-2014-3461: Issues in USB post load checks (bz #1097260, bz # #1096821) %patch0106 -p1 +# Don't use libtool on dtrace, fixes rawhide build (bz #1106968) +%patch0107 -p1 +%patch0108 -p1 +%patch0109 -p1 +%patch0110 -p1 +%patch0111 -p1 +%patch0112 -p1 +%patch0113 -p1 +%patch0114 -p1 +%patch0115 -p1 +%patch0116 -p1 +%patch0117 -p1 %build @@ -1563,6 +1587,9 @@ getent passwd qemu >/dev/null || \ %endif %changelog +* Sun Jun 15 2014 Cole Robinson - 2:2.0.0-7 +- Don't use libtool on dtrace, fixes rawhide build (bz #1106968) + * Sun Jun 08 2014 Fedora Release Engineering - 2:2.0.0-6 - Rebuilt for https://fedoraproject.org/wiki/Fedora_21_Mass_Rebuild