mirror of
https://github.com/brl/mutter.git
synced 2024-12-26 21:02:14 +00:00
5fdb8ab7d6
2003-09-30 Havoc Pennington <hp@redhat.com> * src/testasyncgetprop.c: remove nonstandard header include, #121870
496 lines
12 KiB
C
496 lines
12 KiB
C
/*
|
|
* Copyright (C) 2002 Havoc Pennington
|
|
*
|
|
* Permission to use, copy, modify, distribute, and sell this software
|
|
* and its documentation for any purpose is hereby granted without
|
|
* fee, provided that the above copyright notice appear in all copies
|
|
* and that both that copyright notice and this permission notice
|
|
* appear in supporting documentation.
|
|
*
|
|
* The above copyright notice and this permission notice shall be
|
|
* included in all copies or substantial portions of the Software.
|
|
*
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR
|
|
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
|
|
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
*
|
|
* Except as contained in this notice, the name of The Open Group shall not be
|
|
* used in advertising or otherwise to promote the sale, use or other dealings
|
|
* in this Software without prior written authorization from The Open Group.
|
|
*/
|
|
|
|
#include "async-getprop.h"
|
|
|
|
#include <time.h>
|
|
#include <sys/time.h>
|
|
#include <sys/types.h>
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <unistd.h>
|
|
#include <string.h>
|
|
#include <errno.h>
|
|
#include <signal.h>
|
|
#include <assert.h>
|
|
|
|
#ifndef TRUE
|
|
#define TRUE 1
|
|
#endif
|
|
|
|
#ifndef FALSE
|
|
#define FALSE 0
|
|
#endif
|
|
|
|
#ifndef NULL
|
|
#define NULL ((void*) 0)
|
|
#endif
|
|
|
|
#ifdef HAVE_BACKTRACE
|
|
#include <execinfo.h>
|
|
static void
|
|
print_backtrace (void)
|
|
{
|
|
void *bt[500];
|
|
int bt_size;
|
|
int i;
|
|
char **syms;
|
|
|
|
bt_size = backtrace (bt, 500);
|
|
|
|
syms = backtrace_symbols (bt, bt_size);
|
|
|
|
i = 0;
|
|
while (i < bt_size)
|
|
{
|
|
fprintf (stderr, " %s\n", syms[i]);
|
|
++i;
|
|
}
|
|
|
|
free (syms);
|
|
}
|
|
#else
|
|
static void
|
|
print_backtrace (void)
|
|
{
|
|
fprintf (stderr, "Not compiled with backtrace support\n");
|
|
}
|
|
#endif
|
|
|
|
static int error_trap_depth = 0;
|
|
|
|
static int
|
|
x_error_handler (Display *xdisplay,
|
|
XErrorEvent *error)
|
|
{
|
|
char buf[64];
|
|
|
|
XGetErrorText (xdisplay, error->error_code, buf, 63);
|
|
|
|
if (error_trap_depth == 0)
|
|
{
|
|
print_backtrace ();
|
|
|
|
fprintf (stderr, "Unexpected X error: %s serial %ld error_code %d request_code %d minor_code %d)\n",
|
|
buf,
|
|
error->serial,
|
|
error->error_code,
|
|
error->request_code,
|
|
error->minor_code);
|
|
|
|
exit (1);
|
|
}
|
|
|
|
return 1; /* return value is meaningless */
|
|
}
|
|
|
|
static void
|
|
error_trap_push (Display *xdisplay)
|
|
{
|
|
++error_trap_depth;
|
|
}
|
|
|
|
static void
|
|
error_trap_pop (Display *xdisplay)
|
|
{
|
|
if (error_trap_depth == 0)
|
|
{
|
|
fprintf (stderr, "Error trap underflow!\n");
|
|
exit (1);
|
|
}
|
|
|
|
XSync (xdisplay, False); /* get all errors out of the queue */
|
|
--error_trap_depth;
|
|
}
|
|
|
|
static char*
|
|
my_strdup (const char *str)
|
|
{
|
|
char *s;
|
|
|
|
s = malloc (strlen (str) + 1);
|
|
if (s == NULL)
|
|
{
|
|
fprintf (stderr, "malloc failed\n");
|
|
exit (1);
|
|
}
|
|
strcpy (s, str);
|
|
|
|
return s;
|
|
}
|
|
|
|
static char*
|
|
atom_name (Display *display,
|
|
Atom atom)
|
|
{
|
|
if (atom == None)
|
|
{
|
|
return my_strdup ("None");
|
|
}
|
|
else
|
|
{
|
|
char *xname;
|
|
char *ret;
|
|
|
|
error_trap_push (display);
|
|
xname = XGetAtomName (display, atom);
|
|
error_trap_pop (display);
|
|
if (xname == NULL)
|
|
return my_strdup ("[unknown atom]");
|
|
|
|
ret = my_strdup (xname);
|
|
XFree (xname);
|
|
|
|
return ret;
|
|
}
|
|
}
|
|
|
|
|
|
#define ELAPSED(start_time, current_time) \
|
|
(((((double)current_time.tv_sec - start_time.tv_sec) * 1000000 + \
|
|
(current_time.tv_usec - start_time.tv_usec))) / 1000.0)
|
|
|
|
static struct timeval program_start_time;
|
|
|
|
static Bool
|
|
try_get_reply (Display *xdisplay,
|
|
AgGetPropertyTask *task)
|
|
{
|
|
if (ag_task_have_reply (task))
|
|
{
|
|
int result;
|
|
Atom actual_type;
|
|
int actual_format;
|
|
unsigned long n_items;
|
|
unsigned long bytes_after;
|
|
unsigned char *data;
|
|
char *name;
|
|
struct timeval current_time;
|
|
|
|
gettimeofday (¤t_time, NULL);
|
|
|
|
printf (" %gms (we have a reply for property %ld)\n",
|
|
ELAPSED (program_start_time, current_time),
|
|
ag_task_get_property (task));
|
|
|
|
data = NULL;
|
|
|
|
name = atom_name (xdisplay,
|
|
ag_task_get_property (task));
|
|
printf (" %s on 0x%lx:\n", name,
|
|
ag_task_get_window (task));
|
|
free (name);
|
|
|
|
result = ag_task_get_reply_and_free (task,
|
|
&actual_type,
|
|
&actual_format,
|
|
&n_items,
|
|
&bytes_after,
|
|
&data);
|
|
task = NULL;
|
|
|
|
if (result != Success)
|
|
{
|
|
fprintf (stderr, " error code %d getting reply\n", result);
|
|
}
|
|
else
|
|
{
|
|
name = atom_name (xdisplay, actual_type);
|
|
printf (" actual_type = %s\n", name);
|
|
free (name);
|
|
|
|
printf (" actual_format = %d\n", actual_format);
|
|
|
|
printf (" n_items = %lu\n", n_items);
|
|
printf (" bytes_after = %lu\n", bytes_after);
|
|
|
|
printf (" data = \"%s\"\n", data ? (char*) data : "NULL");
|
|
}
|
|
|
|
return True;
|
|
}
|
|
|
|
return False;
|
|
}
|
|
|
|
static void run_speed_comparison (Display *xdisplay,
|
|
Window window);
|
|
|
|
int
|
|
main (int argc, char **argv)
|
|
{
|
|
Display *xdisplay;
|
|
int i;
|
|
int n_left;
|
|
int n_props;
|
|
Window window;
|
|
const char *window_str;
|
|
char *end;
|
|
Atom *props;
|
|
struct timeval current_time;
|
|
|
|
if (argc < 2)
|
|
{
|
|
fprintf (stderr, "specify window ID\n");
|
|
return 1;
|
|
}
|
|
|
|
window_str = argv[1];
|
|
|
|
end = NULL;
|
|
window = strtoul (window_str, &end, 0);
|
|
if (end == NULL || *end != '\0')
|
|
{
|
|
fprintf (stderr, "\"%s\" does not parse as a window ID\n", window_str);
|
|
return 1;
|
|
}
|
|
|
|
xdisplay = XOpenDisplay (NULL);
|
|
if (xdisplay == NULL)
|
|
{
|
|
fprintf (stderr, "Could not open display\n");
|
|
return 1;
|
|
}
|
|
|
|
if (getenv ("METACITY_SYNC") != NULL)
|
|
XSynchronize (xdisplay, True);
|
|
|
|
XSetErrorHandler (x_error_handler);
|
|
|
|
n_props = 0;
|
|
props = XListProperties (xdisplay, window, &n_props);
|
|
if (n_props == 0 || props == NULL)
|
|
{
|
|
fprintf (stderr, "Window has no properties\n");
|
|
return 1;
|
|
}
|
|
|
|
gettimeofday (&program_start_time, NULL);
|
|
|
|
i = 0;
|
|
while (i < n_props)
|
|
{
|
|
gettimeofday (¤t_time, NULL);
|
|
printf (" %gms (sending request for property %ld)\n",
|
|
ELAPSED (program_start_time, current_time),
|
|
props[i]);
|
|
if (ag_task_create (xdisplay,
|
|
window, props[i],
|
|
0, 0xffffffff,
|
|
False,
|
|
AnyPropertyType) == NULL)
|
|
{
|
|
fprintf (stderr, "Failed to send request\n");
|
|
return 1;
|
|
}
|
|
|
|
++i;
|
|
}
|
|
|
|
XFree (props);
|
|
props = NULL;
|
|
|
|
n_left = n_props;
|
|
|
|
while (TRUE)
|
|
{
|
|
XEvent xevent;
|
|
int connection;
|
|
fd_set set;
|
|
AgGetPropertyTask *task;
|
|
|
|
/* Mop up event queue */
|
|
while (XPending (xdisplay) > 0)
|
|
{
|
|
XNextEvent (xdisplay, &xevent);
|
|
gettimeofday (¤t_time, NULL);
|
|
printf (" %gms (processing event type %d)\n",
|
|
ELAPSED (program_start_time, current_time),
|
|
xevent.xany.type);
|
|
}
|
|
|
|
while ((task = ag_get_next_completed_task (xdisplay)))
|
|
{
|
|
try_get_reply (xdisplay, task);
|
|
n_left -= 1;
|
|
}
|
|
|
|
if (n_left == 0)
|
|
{
|
|
printf ("All %d replies received.\n", n_props);
|
|
break;
|
|
}
|
|
|
|
/* Wake up if we may have a reply */
|
|
connection = ConnectionNumber (xdisplay);
|
|
|
|
FD_ZERO (&set);
|
|
FD_SET (connection, &set);
|
|
|
|
gettimeofday (¤t_time, NULL);
|
|
printf (" %gms (blocking for data %d left)\n",
|
|
ELAPSED (program_start_time, current_time), n_left);
|
|
select (connection + 1, &set, NULL, NULL, NULL);
|
|
}
|
|
|
|
run_speed_comparison (xdisplay, window);
|
|
|
|
return 0;
|
|
}
|
|
|
|
/* This function doesn't have all the printf's
|
|
* and other noise, it just compares async to sync
|
|
*/
|
|
static void
|
|
run_speed_comparison (Display *xdisplay,
|
|
Window window)
|
|
{
|
|
int i;
|
|
int n_props;
|
|
struct timeval start, end;
|
|
int n_left;
|
|
|
|
/* We just use atom values (0 to n_props) % 200, many are probably
|
|
* BadAtom, that's fine, but the %200 keeps most of them valid. The
|
|
* async case is about twice as advantageous when using valid atoms
|
|
* (or the issue may be that it's more advantageous when the
|
|
* properties are present and data is transmitted).
|
|
*/
|
|
n_props = 4000;
|
|
printf ("Timing with %d property requests\n", n_props);
|
|
|
|
gettimeofday (&start, NULL);
|
|
|
|
i = 0;
|
|
while (i < n_props)
|
|
{
|
|
if (ag_task_create (xdisplay,
|
|
window, (Atom) i % 200,
|
|
0, 0xffffffff,
|
|
False,
|
|
AnyPropertyType) == NULL)
|
|
{
|
|
fprintf (stderr, "Failed to send request\n");
|
|
exit (1);
|
|
}
|
|
|
|
++i;
|
|
}
|
|
|
|
n_left = n_props;
|
|
|
|
while (TRUE)
|
|
{
|
|
int connection;
|
|
fd_set set;
|
|
XEvent xevent;
|
|
AgGetPropertyTask *task;
|
|
|
|
/* Mop up event queue */
|
|
while (XPending (xdisplay) > 0)
|
|
XNextEvent (xdisplay, &xevent);
|
|
|
|
while ((task = ag_get_next_completed_task (xdisplay)))
|
|
{
|
|
int result;
|
|
Atom actual_type;
|
|
int actual_format;
|
|
unsigned long n_items;
|
|
unsigned long bytes_after;
|
|
unsigned char *data;
|
|
|
|
assert (ag_task_have_reply (task));
|
|
|
|
data = NULL;
|
|
result = ag_task_get_reply_and_free (task,
|
|
&actual_type,
|
|
&actual_format,
|
|
&n_items,
|
|
&bytes_after,
|
|
&data);
|
|
|
|
if (data)
|
|
XFree (data);
|
|
|
|
n_left -= 1;
|
|
}
|
|
|
|
if (n_left == 0)
|
|
break;
|
|
|
|
/* Wake up if we may have a reply */
|
|
connection = ConnectionNumber (xdisplay);
|
|
|
|
FD_ZERO (&set);
|
|
FD_SET (connection, &set);
|
|
|
|
select (connection + 1, &set, NULL, NULL, NULL);
|
|
}
|
|
|
|
gettimeofday (&end, NULL);
|
|
|
|
printf ("Async time: %gms\n",
|
|
ELAPSED (start, end));
|
|
|
|
gettimeofday (&start, NULL);
|
|
|
|
error_trap_push (xdisplay);
|
|
|
|
i = 0;
|
|
while (i < n_props)
|
|
{
|
|
Atom actual_type;
|
|
int actual_format;
|
|
unsigned long n_items;
|
|
unsigned long bytes_after;
|
|
unsigned char *data;
|
|
|
|
data = NULL;
|
|
if (XGetWindowProperty (xdisplay, window,
|
|
(Atom) i % 200,
|
|
0, 0xffffffff,
|
|
False,
|
|
AnyPropertyType,
|
|
&actual_type,
|
|
&actual_format,
|
|
&n_items,
|
|
&bytes_after,
|
|
&data) == Success)
|
|
{
|
|
if (data)
|
|
XFree (data);
|
|
}
|
|
|
|
++i;
|
|
}
|
|
|
|
error_trap_pop (xdisplay);
|
|
|
|
gettimeofday (&end, NULL);
|
|
|
|
printf ("Sync time: %gms\n",
|
|
ELAPSED (start, end));
|
|
}
|